unit MainUnit;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  ComCtrls, StdCtrls,  Menus, CEFuncproc, Buttons,shellapi,
  ExtCtrls, Dialogs, Clipbrd,debugger,kerneldebugger, assemblerunit,
  registry,{xpman,}math,hexeditor, Gauges, ImgList,commctrl,NewKernelHandler,
  hotkeyhandler,tlhelp32,winsvc,imagehlp,unrandomizer,symbolhandler,
  ActnList,hypermode,autoassembler,injectedpointerscanunit,plugin,savefirstscan,
  foundlisthelper,disassembler, underc, psapi, peinfounit, PEInfoFunctions,
  memscan, formsextra, speedhack2, menuitemExtra, AccessCheck, KIcon, frmCScriptUnit,
  XMLDoc, XMLIntf,  simpleaobscanner, pointervaluelist, ManualModuleLoader,
  windows7taskbar, VistaAltFixUnit;

  //the following are just for compatibility

 

const copypasteversion=4;
const wm_freedebugger=WM_USER+1;
const wm_scandone=WM_USER+2;


type TFlash = class (TThread)
  public
    procedure Execute; override;
    procedure col;
end;


type TToggleWindows = class(TThread)
  private
  public
    constructor Create(CreateSuspended: Boolean);
    procedure Execute; override;
  end;


type grouptype = array[1..6] of boolean;

type TFcontrol= class( TEdit)
  private
  public
    procedure wmMouseWheel (var Msg : TWMMouseWheel); message wm_MouseWheel;

  end;


type
  TMainForm = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    SortByFrozenButton: TButton;
    SortByDescriptionButton: TButton;
    SortByAddressButton: TButton;
    SortByTypeButton: TButton;
    SortByValueButton: TButton;
    UpdateTimer: TTimer;
    FreezeTimer: TTimer;
    PopupMenu2: TPopupMenu;
    Deletethisrecord1: TMenuItem;
    Browsethismemoryregion1: TMenuItem;
    Calculatenewvaluepart21: TMenuItem;
    Freezealladdresses2: TMenuItem;
    sep1: TMenuItem;
    Unfreezealladdresses1: TMenuItem;
    N1: TMenuItem;
    Groupoption1: TMenuItem;
    Settogroup11: TMenuItem;
    Settogroup21: TMenuItem;
    Settogroup31: TMenuItem;
    Settogroup41: TMenuItem;
    Settonogroup1: TMenuItem;
    N2: TMenuItem;
    N3: TMenuItem;
    Sortaddressesbygroup1: TMenuItem;
    N4: TMenuItem;
    Copy1: TMenuItem;
    Paste1: TMenuItem;
    Cut1: TMenuItem;
    Setbreakpoint1: TMenuItem;
    SetHotkey1: TMenuItem;
    Findoutwhatreadsfromthisaddress1obsolete: TMenuItem;
    N5: TMenuItem;
    Panel4: TPanel;
    advancedbutton: TSpeedButton;
    Label7: TLabel;
    CommentButton: TSpeedButton;
    Panel5: TPanel;
    ProcessLabel: TLabel;
    foundcountlabel: TLabel;
    ScanText: TLabel;
    Label4: TLabel;
    Label8: TLabel;
    LoadButton: TSpeedButton;
    SaveButton: TSpeedButton;
    Label6: TLabel;
    SpeedButton2: TSpeedButton;
    SpeedButton3: TSpeedButton;
    GroupBox1: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    Windows: TRadioButton;
    Readonly: TCheckBox;
    FromAddress: TMemo;
    ToAddress: TMemo;
    NewScan: TButton;
    NextScanButton: TButton;
    ScanType: TComboBox;
    VarType: TComboBox;
    btnMemoryView: TButton;
    Button1: TButton;
    ProgressBar1: TProgressBar;
    HexadecimalCheckbox: TCheckBox;
    UndoScan: TButton;
    rbBit: TRadioButton;
    rbDec: TRadioButton;
    scanvalue: TEdit;
    PopupMenu1: TPopupMenu;
    Browsethismemoryarrea1: TMenuItem;
    Removeselectedaddresses1: TMenuItem;
    Selectallitems1: TMenuItem;
    OpenDialog1: TOpenDialog;
    SaveDialog1: TSaveDialog;
    TopDisabler: TTimer;
    emptypopup: TPopupMenu;
    ccpmenu: TPopupMenu;
    Cut2: TMenuItem;
    Copy2: TMenuItem;
    Paste2: TMenuItem;
    Splitter1: TSplitter;
    SpeedButton4: TSpeedButton;
    cbCaseSensitive: TCheckBox;
    cbFastScan: TCheckBox;
    btnShowRegions: TButton;
    Foundlist3: TListView;
    Findoutwhataccessesthisaddress1: TMenuItem;
    Showashexadecimal1: TMenuItem;
    Settogroup42: TMenuItem;
    Settogroup51: TMenuItem;
    cbFasterScan: TCheckBox;
    rbAllMemory: TRadioButton;
    Panel7: TPanel;
    SpeedButton1: TSpeedButton;
    cbPauseWhileScanning: TCheckBox;
    btnSetSpeedhack: TButton;
    Label51: TLabel;
    Label52: TLabel;
    Edit2: TEdit;
    Edit1: TEdit;
    Change1: TMenuItem;
    Description1: TMenuItem;
    Address1: TMenuItem;
    ype1: TMenuItem;
    Value1: TMenuItem;
    LabelModifiedmem: TLabel;
    pnlFloat: TPanel;
    rt3: TRadioButton;
    rt1: TRadioButton;
    rt2: TRadioButton;
    cbUnicode: TCheckBox;
    cbUnrandomizer: TCheckBox;
    Changescript1: TMenuItem;
    ActionList1: TActionList;
    actSave: TAction;
    actOpen: TAction;
    ImageList1: TImageList;
    actAutoAssemble: TAction;
    Forcerechecksymbols1: TMenuItem;
    Label5: TLabel;
    Label38: TLabel;
    Smarteditaddresses1: TMenuItem;
    Label53: TLabel;
    Pointerscanforthisaddress1: TMenuItem;
    Label55: TLabel;
    Label57: TLabel;
    Label58: TLabel;
    Plugins1: TMenuItem;
    Label59: TLabel;
    UpdateFoundlisttimer: TTimer;
    mode16: TCheckBox;
    Browsethismemoryregioninthedisassembler1: TMenuItem;
    AutoAttachTimer: TTimer;
    Button2: TButton;
    Button4: TButton;
    LogoPanel: TPanel;
    Logo: TImage;
    ScrollBox1: TScrollBox;
    HeaderControl1: THeaderControl;
    Panel3: TPanel;
    Label30: TLabel;
    Label29: TLabel;
    Label12: TLabel;
    Label27: TLabel;
    Label15: TLabel;
    Label16: TLabel;
    Label13: TLabel;
    Label18: TLabel;
    Label23: TLabel;
    Label28: TLabel;
    Label3: TLabel;
    Label9: TLabel;
    Label10: TLabel;
    Label11: TLabel;
    Label14: TLabel;
    Label17: TLabel;
    Label19: TLabel;
    Label20: TLabel;
    Label21: TLabel;
    Label22: TLabel;
    Label24: TLabel;
    Label25: TLabel;
    Label26: TLabel;
    Label31: TLabel;
    Label32: TLabel;
    Label33: TLabel;
    Label34: TLabel;
    Label35: TLabel;
    Label36: TLabel;
    Label37: TLabel;
    Label39: TLabel;
    Label40: TLabel;
    Label41: TLabel;
    Label42: TLabel;
    Label43: TLabel;
    Label44: TLabel;
    Label45: TLabel;
    Label46: TLabel;
    Label47: TLabel;
    Label48: TLabel;
    Label49: TLabel;
    Label50: TLabel;
    CheckBox1: TCheckBox;
    CheckBox2: TCheckBox;
    CheckBox3: TCheckBox;
    CheckBox4: TCheckBox;
    CheckBox5: TCheckBox;
    CheckBox6: TCheckBox;
    CheckBox7: TCheckBox;
    vscrollpanel: TPanel;
    ScrollBar1: TScrollBar;
    Panel14: TPanel;
    btnSetSpeedhack2: TButton;
    editSH2: TEdit;
    Label54: TLabel;
    tbSpeed: TTrackBar;
    Label56: TLabel;
    Label60: TLabel;
    cbSpeedhack: TCheckBox;
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    Process1: TMenuItem;
    Help1: TMenuItem;
    Edit3: TMenuItem;
    About1: TMenuItem;
    OpenProcess1: TMenuItem;
    Save1: TMenuItem;
    Load1: TMenuItem;
    Settings1: TMenuItem;
    N6: TMenuItem;
    a1: TMenuItem;
    b1: TMenuItem;
    c1: TMenuItem;
    d1: TMenuItem;
    e1: TMenuItem;
    CreateProcess1: TMenuItem;
    New1: TMenuItem;
    N7: TMenuItem;
    ools1: TMenuItem;
    N8: TMenuItem;
    Helpindex1: TMenuItem;
    actScriptEngine: TAction;
    Plugins2: TMenuItem;
    actMemoryView: TAction;
    Label61: TLabel;
    actOpenProcesslist: TAction;
    procedure ShowProcessListButtonClick(Sender: TObject);
    procedure NewScanClick(Sender: TObject);
    procedure NextScanButtonClick(Sender: TObject);
    procedure btnMemoryViewClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure AddressKeyPress(Sender: TObject; var Key: Char);
    procedure Panel1DragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure Panel1DragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure FoundListDblClick(Sender: TObject);
    procedure Browsethismemoryarrea1Click(Sender: TObject);
    procedure UpdateTimerTimer(Sender: TObject);
    procedure FreezeTimerTimer(Sender: TObject);
    procedure ScrollBar1Change(Sender: TObject);
    procedure Label28Click(Sender: TObject);
    procedure AddressClick(Sender: TObject);
    procedure TypeClick(Sender: TObject);
    procedure ValueClick(Sender: TObject);
    procedure Browsethismemoryregion1Click(Sender: TObject);
    procedure Label24ContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure Deletethisrecord1Click(Sender: TObject);
    procedure SortByFrozenButtonClick(Sender: TObject);
    procedure SortByDescriptionButtonClick(Sender: TObject);
    procedure SortByAddressButtonClick(Sender: TObject);
    procedure SortByTypeButtonClick(Sender: TObject);
    procedure SortByValueButtonClick(Sender: TObject);
    procedure ScanvalueoldKeyPress(Sender: TObject; var Key: Char);
    procedure Calculatenewvaluepart21Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure ScanTypeChange(Sender: TObject);
    procedure VarTypeChange(Sender: TObject);
    procedure LogoClick(Sender: TObject);
    procedure WindowsClick(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure SpeedButton2Click(Sender: TObject);
    procedure SpeedButton3Click(Sender: TObject);
    procedure Selectallitems1Click(Sender: TObject);
    procedure Label37Click(Sender: TObject);
    procedure Freezealladdresses2Click(Sender: TObject);
    procedure SlectItem(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PopupMenu2Popup(Sender: TObject);
    procedure CheckBox2MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure CheckBox1Click(Sender: TObject);
    procedure Unfreezealladdresses1Click(Sender: TObject);
    procedure PopupMenu1Popup(Sender: TObject);
    procedure Removeselectedaddresses1Click(Sender: TObject);
    procedure FControlKeyPress(Sender: TObject; var Key: Char);
    procedure FControlKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure ScrollBar1Enter(Sender: TObject);
    procedure FControlExit(Sender: TObject);
    procedure Panel1Click(Sender: TObject);
    procedure FControlEnter(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure CommentButtonClick(Sender: TObject);
    procedure CommentButtonMouseMove(Sender: TObject; Shift: TShiftState;
      X, Y: Integer);
    procedure SettogroupXClick(Sender: TObject);
    procedure Settonogroup1Click(Sender: TObject);
    procedure SetPrioritys1Click(Sender: TObject);
    procedure Copy1Click(Sender: TObject);
    procedure Cut1Click(Sender: TObject);
    procedure Paste1Click(Sender: TObject);
    procedure Panel1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Sortaddressesbygroup1Click(Sender: TObject);
    procedure Setbreakpoint1Click(Sender: TObject);
    procedure TopDisablerTimer(Sender: TObject);
    procedure Panel1Resize(Sender: TObject);
    procedure ScrollBar1Scroll(Sender: TObject; ScrollCode: TScrollCode;
      var ScrollPos: Integer);
    procedure advancedbuttonClick(Sender: TObject);
    procedure HexadecimalCheckboxClick(Sender: TObject);
    procedure SetHotkey1Click(Sender: TObject);
    procedure Findoutwhatreadsfromthisaddress1obsoleteClick(Sender: TObject);
    procedure UndoScanClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure rbBitClick(Sender: TObject);
    procedure rbDecClick(Sender: TObject);
    procedure Cut2Click(Sender: TObject);
    procedure Copy2Click(Sender: TObject);
    procedure Paste2Click(Sender: TObject);
    procedure ccpmenuPopup(Sender: TObject);
    procedure Splitter1CanResize(Sender: TObject; var NewSize: Integer;
      var Accept: Boolean);
    procedure Splitter1Moved(Sender: TObject);
    procedure SettingsClick(Sender: TObject);
    procedure cbCaseSensitiveClick(Sender: TObject);
    procedure LogoMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure directionclick(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure btnShowRegionsClick(Sender: TObject);
    procedure Findoutwhataccessesthisaddress1Click(Sender: TObject);
    procedure OpenProcesslist1Click(Sender: TObject);
    procedure CloseCheatEngine1Click(Sender: TObject);
    procedure Showashexadecimal1Click(Sender: TObject);
    procedure OpenMemorybrowser1Click(Sender: TObject);
    procedure cbFastScanClick(Sender: TObject);
    procedure rbAllMemoryClick(Sender: TObject);
    procedure cbPauseWhileScanningClick(Sender: TObject);
    procedure btnSetSpeedhackClick(Sender: TObject);
    procedure Description1Click(Sender: TObject);
    procedure Address1Click(Sender: TObject);
    procedure ype1Click(Sender: TObject);
    procedure Value1Click(Sender: TObject);
    procedure ProcessLabelDblClick(Sender: TObject);
    procedure ProcessLabelMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure cbUnrandomizerClick(Sender: TObject);
    procedure cbUnrandomizerMouseDown(Sender: TObject;
      Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure Foundlist3CustomDrawItem(Sender: TCustomListView;
      Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
    procedure actOpenExecute(Sender: TObject);
    procedure actSaveExecute(Sender: TObject);
    procedure actAutoAssembleExecute(Sender: TObject);
    procedure Changescript1Click(Sender: TObject);
    procedure Forcerechecksymbols1Click(Sender: TObject);
    procedure Label5Click(Sender: TObject);
    procedure Smarteditaddresses1Click(Sender: TObject);
    procedure Pointerscanforthisaddress1Click(Sender: TObject);
    procedure Label53Click(Sender: TObject);
    procedure Label57Click(Sender: TObject);
    procedure Foundlist3Data(Sender: TObject; Item: TListItem);
    procedure UpdateFoundlisttimerTimer(Sender: TObject);
    procedure Foundlist3KeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure mode16Click(Sender: TObject);
    procedure Label59Click(Sender: TObject);
    procedure Browsethismemoryregioninthedisassembler1Click(
      Sender: TObject);
    procedure AutoAttachTimerTimer(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure ScanTypeKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure HeaderControl1SectionClick(HeaderControl: THeaderControl;
      Section: THeaderSection);
    procedure HeaderControl1SectionResize(HeaderControl: THeaderControl;
      Section: THeaderSection);
    procedure FormDestroy(Sender: TObject);
    procedure tbSpeedChange(Sender: TObject);
    procedure btnSetSpeedhack2Click(Sender: TObject);
    procedure cbSpeedhackClick(Sender: TObject);
    procedure Edit2Change(Sender: TObject);
    procedure Process1Click(Sender: TObject);
    procedure About1Click(Sender: TObject);
    procedure CreateProcess1Click(Sender: TObject);
    procedure Helpindex1Click(Sender: TObject);
    procedure New1Click(Sender: TObject);
    procedure actScriptEngineExecute(Sender: TObject);
    procedure File1Click(Sender: TObject);
    procedure Label61Click(Sender: TObject);
    procedure actOpenProcesslistExecute(Sender: TObject);
    procedure Panel5Resize(Sender: TObject);
    procedure Foundlist3Resize(Sender: TObject);
  private
    oldscanvalue2text: string;
    fcontrol: tfcontrol;
    aaa:single;
    hotkeypressed: integer;

    cancelbutton: Tbutton; //cancel button that spawns during a scan, disabled initially to prevent doubleclick accidents
    cancelbuttonenabler: TTimer; //timer that will enable the cancelbutton after 3 seconds

    CreateCustomScanButton: TButton;
    EditCustomScanButton: TButton;
    CustomScanScripts: array of record
                         name: string;
                         data: TStringlist;
                         CustomScanType: TCustomScanType;
                       end;



    oldwidth,oldheight: integer;
    newaddress: Dword;
    isbit: boolean;
    tempbitmap: Tbitmap;
    dontrunshow:boolean;

    LastWasHex: boolean;
    dontconvert:boolean;
    FlashProcessButton: TFlash;
    oldvartype: integer;

    unrandomize: Tunrandomize;


    scantext2: tlabel;
    andlabel: tlabel;
    scanvalue2: tedit;
    cbpercentage: tcheckbox;

    ceclipboardformat: THandle;
    reinterpretcheck: integer;

    ffoundcount: int64;

    SaveFirstScanThread: TSaveFirstScanThread;

    foundlist: Tfoundlist;
    lastscantype: integer;

    editingscript: boolean;
    editedscript: integer;

    oldhandle: thandle;

    hexstateForIntTypes: boolean;

    function openprocessPrologue: boolean;
    procedure openProcessEpilogue(oldprocessname: string; oldprocess: dword; oldprocesshandle: dword;autoattachopen: boolean=false);
    procedure doNewScan;
    procedure SetExpectedTableName;
    procedure autoattachcheck;
    procedure aprilfoolsscan;
    function CheckIfSaved: Boolean;
    procedure checkpaste;
    procedure hotkey(var Message: TMessage); message WM_HOTKEY;
    procedure WMGetMinMaxInfo(var Message: TMessage); message WM_GETMINMAXINFO;
    procedure freedebugger(var Message: TMessage); message WM_FREEDEBUGGER;
    procedure pointerscanner_addaddress(var Message: TMessage); message WM_COPYDATA;
    procedure Hotkey2(var Message:TMessage); message wm_hotkey2;
    procedure ScanDone(var message: TMessage); message WM_SCANDONE;
    procedure FreezeThem;
    Procedure Edit;
    function paste(simplecopypaste: boolean): integer;
    procedure CopySelectedRecords;
    procedure DeleteRecords;
    procedure Deletegroups(groups: grouptype);

    procedure exceptionhandler(Sender: TObject; E: Exception);
    procedure ResizeScreen;
    procedure SetReadWriteBreakpoint(address: dword; size: dword);
    procedure toggleWindow;
    procedure adjustbringtofronttext;

    procedure scanEpilogue(canceled: boolean);
    procedure CancelbuttonClick(sender: TObject);
    procedure CancelbuttonenablerInterval(sender: TObject);
    procedure CreateCustomScanButtonClick(sender: TObject);
    procedure EditCustomScanButtonClick(sender: TObject);

    procedure changeScriptCallback(script: string; changed: boolean);

    //processlist
    procedure ProcessItemClick(Sender: TObject);

    //property functions
    function GetRoundingType: TRoundingType;
    procedure SetRoundingType(rt: TRoundingType);
    function getScanStart: Dword;
    procedure setScanStart(newscanstart: dword);
    function getScanStop: Dword;
    procedure setScanStop(newscanstop: dword);
    function getFastscan: boolean;
    procedure setFastScan(state: boolean);
    function getScanReadonly: boolean;
    procedure setScanReadOnly(state: boolean);

    function getSelectedCustomScanData: TStringlist;
    function getSelectedCustomScanType: TCustomScanType;
    function getSelectedVariableType: TVariableType;
    procedure setfoundcount(x: int64);


  public
    { Public declarations }
   
    test: single;
    itemshavechanged: boolean;

    debugproc: boolean;
    autoopen: boolean; //boolean set when table is opened by other means than user file picker

    oldNumberOfRecords: Integer;
    oldMemrec: array of memoryrecord;
    OldComments: String;
    oldcodelistcount: integer;

    NumberOfRecords: Integer;
    memrec: array of memoryrecord;
    FrozenFvalue: Array of Double;
    FrozenStrings: Array of string;
    FrozenBytes: array of array of byte;

    Hotkeystrings: Array of string;
    Hotkeys: array of integer;

    Selected: Array of Boolean;
    lastselected: Integer;
    LastLastSelected: Integer;
    FirstShiftSelected: Integer; //-1 = no shift pressed before else it contains the record that has been selected


    lastsave: array of memoryrecord;
    lastsavecount: Integer;

    NumberofLines: integer;
    freezedirection: array of TLabel;
    frozenbox:   array of TCheckbox;
    description: array of TLabel;
    address:     array of TLabel;
    ValType:     array of TLabel;
    Value:       array of TLabel;
    Select:      array of TLabel;

    Priority: Dword;
    memimage: TMemorystream;

    canceled: boolean;

    originalheight:integer;
    originalwidth:integer;

    fronttext: string;


    aprilfools: boolean;
    editedsincelastsave: boolean;

    autoattachlist: tstringlist;

    memscan: tmemscan;

    procedure ChangedHandle(Sender: TObject);
    procedure plugintype0click(Sender:tObject);
    procedure plugintype5click(Sender:tObject);
    procedure OnToolsClick(sender: TObject);    
    procedure AddToRecord(Line: Integer);
    procedure AddAutoAssembleScript(script:string);
    procedure reinterpretaddresses;


    procedure ClearList; 
    procedure Updatelist;
    Procedure UpdateScreen;
    procedure SetWriteBreakpoint(address: dword; size: dword);
    procedure SetReadBreakpoint(address: dword; size: dword);
    procedure reserveMem;
    procedure ChangeValue(Itemnr: integer; NewValue:String);
    function  getStringFromRecord(itemid: Integer):string;
    procedure EnableHypermode;
    procedure disableHypermode;
    Procedure UpdateScanType;
    procedure enableGui(isnextscan: boolean);
    procedure disableGui;
    procedure SpawnCancelButton;
    procedure DestroyCancelButton;
    procedure disableautoassemblecheat(i: integer);
    procedure enableautoassemblecheat(i: integer);
    procedure addaddress(description: string; address:dword; const offsets: array of dword; offsetcount: integer; ispointer: boolean; vartype: integer; length: integer; startbit:integer; unicode: boolean); overload;
    procedure addaddress(description: string; address:dword; const offsets: array of dword; offsetcount: integer; ispointer: boolean; vartype: integer; length: integer; startbit:integer; unicode,showashex: boolean); overload;
    property foundcount: int64 read ffoundcount write setfoundcount;
    property RoundingType: TRoundingType read GetRoundingType write SetRoundingType;
    property ScanStart: dword read getScanStart write setScanStart;
    property ScanStop: dword read getScanStop write setScanStop;
    property FastScan: boolean read getFastscan write setFastscan;
    property ScanReadOnly: boolean read getScanReadonly write setScanReadonly;
    property SelectedCustomScanData: Tstringlist read getSelectedCustomScanData;
    property SelectedCustomScanType: TCustomScanType read getSelectedCustomScanType;
    property SelectedVariableType: TVariableType read getSelectedVariableType;
  end;

var
  MainForm: TMainForm;
  ToggleWindows: TTogglewindows;

implementation

uses mainunit2,ProcessWindowUnit, MemoryBrowserFormUnit, TypePopup,
  AddAddress, HotKeys, standaloneunit, aboutunit,
  CommentsUnit, formsettingsunit, Changeoffsetunit, FoundCodeUnit, advancedoptionsunit,
  formScanningUnit, formDifferentBitSizeUnit,OpenSave,
  formMemoryTrainerUnit, MemoryTrainerDesignUnit, formhotkeyunit,
  formAddressChangeUnit, formmemoryregionsunit,formPointerOrPointeeUnit,
  frmProcessWatcherUnit, formProcessInfo, frmautoinjectunit,
  PasteTableentryFRM, pointerscannerfrm, PointerscannerSettingsFrm,
  InjectedpointerscanornotFRM, frmGDTunit, frmFunctionlistUnit, frmFloatingPointPanelUnit;

{$R *.DFM}

var ncol: TColor;
procedure TFlash.Col;
begin
  mainform.panel7.Color:=ncol;
end;

procedure TFlash.Execute;
var red,green: byte;
    decreasered: boolean;
begin

{$ifndef ceasinjecteddll}
  freeonterminate:=true; 
  decreasered:=true;
  red:=254;
  green:=0;
  while not terminated do
  begin
    if decreasered then
    begin
      dec(red,2);
      inc(green,2);
      if green>=250 then decreasered:=false;
    end
    else
    begin
      inc(red,2);
      dec(green,2);
      if red>=254 then
        decreasered:=true;
    end;
    ncol:=(green shl 8)+red;
    synchronize(col); //sigh (without it works too, but at least with this I know for sure it works.

    sleep(10);
  end;

{$endif}
  mainform.Panel7.Color:=clBtnFace;        
end;

constructor TToggleWindows.Create(CreateSuspended: Boolean);
begin
  freeonterminate:=true;
  inherited Create(CreateSuspended);
end;

procedure TToggleWindows.Execute;
begin
  toggleotherwindows;
  togglewindows:=nil;
end;

procedure TMainForm.WMGetMinMaxInfo(var Message: TMessage);
var MMInfo: ^MINMAXINFO;
begin //the constraint function of the form behaves weird when draging from the top or left side, so I have to do this myself.
//mainform.pix
  MMInfo:=ptr(message.LParam);
  if pixelsperinch=96 then
  begin
    MMInfo.ptMinTrackSize:=point(490,460);
  end;
end;

procedure TFcontrol.wmMouseWheel(var msg: TWMMousewheel);
var k: word;

begin
  //move down message

  if msg.WheelDelta>0 then
    k:=vk_up
  else
    k:=vk_down;

  mainform.FControlKeyDown(self, k,[]);
end;

procedure TMainform.Hotkey2(var Message:TMessage);
var i:integer;
    a,b: single;
    s: string;
begin
  case message.WParam of
    0:
    begin
      //popup/hide CE
      if advancedoptions.Pausebutton.Down then
      begin
        errorbeep;
        exit;
      end;

      beep;

      if formsettings.cbHideAllWindows.checked then
      begin
        ToggleWindow;

        if formsettings.cbCenterOnPopup.checked then
          if not allwindowsareback then
            setwindowpos(mainform.Handle,HWND_NOTOPMOST,(screen.Width div 2)-(mainform.Width div 2),(screen.Height div 2)-(mainform.height div 2),mainform.Width,mainform.Height,SWP_NOZORDER or SWP_NOACTIVATE);

        if not allwindowsareback then application.BringToFront else
          setforegroundwindow(lastforeground);

        adjustbringtofronttext;
        exit;
      end;

      application.BringToFront;
      SetForegroundWindow(mainform.Handle);

      mainform.SetFocus;

      if formsettings.cbCenterOnPopup.checked then
        setwindowpos(mainform.Handle,HWND_NOTOPMOST,(screen.Width div 2)-(mainform.Width div 2),(screen.Height div 2)-(mainform.height div 2),mainform.Width,mainform.Height,SWP_NOZORDER or SWP_NOACTIVATE);

      formstyle:=fsStayOnTop;
    end;

    1: //Pause
    begin
      with advancedoptions do
      begin
        pausedbyhotkey:=true;
        pausebutton.down:=not pausebutton.down;
        pausebutton.Click;
        pausedbyhotkey:=false;
      end;
    end;

    2: //speedhack
    begin
      if cbSpeedhack.Enabled then
      begin
        beep;
        cbSpeedhack.checked:=not cbSpeedhack.Checked;
      end;
    end;

    //3..7=set speedhack speed
    3:
    begin
      if cbspeedhack.enabled then
      begin
        cbspeedhack.Checked:=true;
        if cbspeedhack.checked then
        begin
          edit2.Text:=format('%.2f',[speedhackspeed1.speed]);
          edit1.Text:=inttostr(speedhackspeed1.sleeptime);
          btnSetSpeedhack.Click;
        end;
      end;
    end;

    4:
    begin
      if cbspeedhack.enabled then
      begin
        cbspeedhack.Checked:=true;
        if cbspeedhack.checked then
        begin
          edit2.Text:=format('%.2f',[speedhackspeed2.speed]);
          edit1.Text:=inttostr(speedhackspeed2.sleeptime);
          btnSetSpeedhack.Click;
        end;
      end;
    end;

    5:
    begin
      if cbspeedhack.enabled then
      begin
        cbspeedhack.Checked:=true;
        if cbspeedhack.checked then
        begin
          edit2.Text:=format('%.2f',[speedhackspeed3.speed]);
          edit1.Text:=inttostr(speedhackspeed3.sleeptime);
          btnSetSpeedhack.Click;
        end;
      end;
    end;

    6:
    begin
      if cbspeedhack.enabled then
      begin
        cbspeedhack.Checked:=true;
        if cbspeedhack.checked then
        begin
          edit2.Text:=format('%.2f',[speedhackspeed4.speed]);
          edit1.Text:=inttostr(speedhackspeed4.sleeptime);
          btnSetSpeedhack.Click;
        end;
      end;
    end;

    7:
    begin
      if cbspeedhack.enabled then
      begin
        cbspeedhack.Checked:=true;
        if cbspeedhack.checked then
        begin
          edit2.Text:=format('%.2f',[speedhackspeed5.speed]);
          edit1.Text:=inttostr(speedhackspeed5.sleeptime);
          btnSetSpeedhack.Click;
        end;
      end;
    end;

    8:
    begin
      //increase speed
      try
        if cbspeedhack.Enabled then
        begin
          cbspeedhack.Checked:=true;
          if cbspeedhack.Checked then
          begin
            a:=strtofloat(edit2.text);
            a:=a+speedupdelta;
            edit2.Text:=format('%.2f',[a]);
            btnSetSpeedhack.Click;
          end;
        end;
      except

      end;
    end;


    9:
    begin
      //decrease speed
      try
        if cbspeedhack.Enabled then
        begin
          cbspeedhack.Checked:=true;
          if cbspeedhack.Checked then
          begin
            b:=strtofloat(edit2.text);
            b:=b-slowdowndelta;
            edit2.Text:=format('%.2f',[b]);
            btnSetSpeedhack.Click;
          end;
        end;
      except

      end;
    end;

    10..18: //Change type (if possible)
    begin
      if vartype.Enabled then
        vartype.itemindex:=message.WParam-3
      else
      begin
        errorbeep;
      end;
    end;

    19://new scan
    begin
      if not newscan.Enabled then exit; //only when no process is opened
      if (formscanning<>nil) and (formscanning.Visible) then exit; //it's scanning

      i:=vartype.ItemIndex;

      if newscan.Caption=strNewScan then
        newscan.Click; //start new scan

      vartype.ItemIndex:=i;
      vartype.OnChange(vartype); //set previous type
    end;

    20: //new scan Exact value
    begin

      if not newscan.Enabled then exit;
      if (formscanning<>nil) and (formscanning.Visible) then exit; //it's scanning
      i:=vartype.itemindex;
      s:=scanvalue.Text;
      if s='' then exit;      

      if newscan.Caption=strNewScan then
        newscan.Click; //start new scan

      vartype.ItemIndex:=i;
      vartype.OnChange(vartype); //set previous type

      scanvalue.Text:=s;
      newscan.Click;
    end;

    21: //new scan unknown initial value
    begin
      if not newscan.Enabled then exit;
      if (formscanning<>nil) and (formscanning.Visible) then exit; //it's scanning

      i:=vartype.ItemIndex;

      if newscan.Caption=strNewScan then
        newscan.Click; //start new scan

      vartype.ItemIndex:=i;
      vartype.OnChange(vartype);

      scantype.ItemIndex:=scantype.Items.IndexOf(StrUnknownInitialValue);
      scantype.OnChange(scantype);

      newscan.Click;
    end;

    22: //next scan Exact value
    begin
      if not newscan.Enabled then exit;
      if (formscanning<>nil) and (formscanning.Visible) then exit; //it's scanning

      if nextscanbutton.Enabled then
      begin
        scantype.ItemIndex:=scantype.Items.IndexOf(StrExactValue);
        scantype.OnChange(scantype);

        nextscanbutton.click;
      end
      else Errorbeep;
    end;

    23: //next scan IncreasedValue
    begin
      if not newscan.Enabled then exit;
      if (formscanning<>nil) and (formscanning.Visible) then exit; //it's scanning

      if nextscanbutton.Enabled then
      begin
        scantype.ItemIndex:=scantype.Items.IndexOf(StrIncreasedValue);
        scantype.OnChange(scantype);

        nextscanbutton.click;
      end
      else Errorbeep;
    end;

    24: //next scan DecreasedValue
    begin
      if not newscan.Enabled then exit;
      if (formscanning<>nil) and (formscanning.Visible) then exit; //it's scanning

      if nextscanbutton.Enabled then
      begin
        scantype.ItemIndex:=scantype.Items.IndexOf(StrDecreasedValue);
        scantype.OnChange(scantype);

        nextscanbutton.click;
      end
      else Errorbeep;
    end;

    25: //next scan ChangedValue
    begin
      if not newscan.Enabled then exit;
      if (formscanning<>nil) and (formscanning.Visible) then exit; //it's scanning

      if nextscanbutton.Enabled then
      begin
        scantype.ItemIndex:=scantype.Items.IndexOf(StrChangedValue);
        scantype.OnChange(scantype);

        nextscanbutton.click;
      end
      else Errorbeep;
    end;

    26: //next scan unchangedValue
    begin
      if not newscan.Enabled then exit;
      if (formscanning<>nil) and (formscanning.Visible) then exit; //it's scanning

      if nextscanbutton.Enabled then
      begin
        scantype.ItemIndex:=scantype.Items.IndexOf(StrUnchangedValue);
        scantype.OnChange(scantype);

        nextscanbutton.click;
      end
      else Errorbeep;
    end;

    27: //next scan Same as first
    begin
      if not newscan.Enabled then exit;
      if (formscanning<>nil) and (formscanning.Visible) then exit; //it's scanning

      if nextscanbutton.Enabled then
      begin
        scantype.ItemIndex:=scantype.Items.IndexOf(strSameAsFirstScan);
        scantype.OnChange(scantype);

        nextscanbutton.click;
      end
      else Errorbeep;
    end;


    28: //undo lastscan
    begin
      if not newscan.Enabled then exit;
      if (formscanning<>nil) and (formscanning.Visible) then exit; //it's scanning

      if undoscan.Enabled then
        undoscan.Click
      else
        Errorbeep;
    end;

    29: //cancel current scan
    begin
      if (formscanning<>nil) and (formscanning.btnCancel.Enabled) then
        formscanning.btnCancel.Click;
    end;

    30: //debug->run
    begin
      MemoryBrowser.Run1.Click;
    end;




  end;

end;

procedure TMainForm.hotkey(var Message: TMessage); //stays because the old hotkeyhandler is still used in some places
var x: TDevMode;
    i: integer;
    c: integer;
begin
  if ((hotkeyform<>nil) and (hotkeyform.Visible)) or ((formhotkey<>nil) and (formhotkey.visible)) then exit;

  if Message.wparam=0 then
  begin
    //bring to front
    try
      unregisterhotkey(mainform.handle,0);

    if advancedoptions.Pausebutton.Down then
    begin
      beep;
      sleep(100);
      beep;
      sleep(100);
      beep;
      sleep(100);
      exit;
    end;

    beep;

    if formsettings.cbHideAllWindows.checked then
    begin
      ToggleWindow;

//      ToggleOtherWindows;

      if formsettings.cbCenterOnPopup.checked then
        if not allwindowsareback then
          setwindowpos(mainform.Handle,HWND_NOTOPMOST,(screen.Width div 2)-(mainform.Width div 2),(screen.Height div 2)-(mainform.height div 2),mainform.Width,mainform.Height,SWP_NOZORDER or SWP_NOACTIVATE);

      if not allwindowsareback then application.BringToFront else
      begin
        setforegroundwindow(lastforeground);
     //   setactivewindow(lastactive);
      end;

      adjustbringtofronttext;
      exit;
    end;


   // if length(windowlist)<>0 then
    application.BringToFront;

    if formsettings.cbCenterOnPopup.checked then
      setwindowpos(mainform.Handle,HWND_NOTOPMOST,(screen.Width div 2)-(mainform.Width div 2),(screen.Height div 2)-(mainform.height div 2),mainform.Width,mainform.Height,SWP_NOZORDER or SWP_NOACTIVATE);

    formstyle:=fsStayOnTop;

    finally
      registerhotkey(mainform.handle,0,message.lparamlo,message.LParamHi); //restore the hotkey
    end;
  end;


  if message.WParam=2 then //toggle speedhack
  begin
  
    try
      unregisterhotkey(mainform.handle,2);
      if cbSpeedhack.Enabled then
      begin
        beep;
        cbSpeedhack.checked:=not cbSpeedhack.Checked;
      end;
    finally
      registerhotkey(mainform.handle,2,message.lparamlo,message.LParamHi); //restore the hotkey
    end;

  end;

  if message.WParam>=10 then //it's a record with a hotkey
  begin
    for i:=0 to numberofrecords-1 do
    begin //find the record
      if message.WParam=hotkeys[i] then
      begin
        if memrec[i].VarType=255 then
        begin
          if memrec[i].Frozen then
            disableautoassemblecheat(i)
          else
            enableautoassemblecheat(i);
            
          updatescreen;
          exit;
        end;

        //set the value to what it was when the hotkey got set
        hotkeypressed:=i;
        memrec[i].Frozen:=true;
        FreezeThem;
        memrec[i].Frozen:=false;
        hotkeypressed:=-1;
        exit;
      end;
    end;
  end;
end;
//----------------------------------

function TMainform.getSelectedCustomScanData: TStringlist;
var index: integer;
begin

  index:=scantype.itemindex;
  if (getSelectedVariableType=vtCustom) and (index>=0) then
    result:=CustomScanScripts[index].data
  else
    result:=nil;
end;

function TMainform.getSelectedCustomScanType: TCustomScanType;
var index: integer;
begin
  index:=scantype.itemindex;
  if (getSelectedVariableType=vtCustom) and (index>=0) then
    result:=CustomScanScripts[index].CustomScanType
  else
    result:=cstNone;
end;

function TMainform.getSelectedVariableType: TVariableType;
{wrapper for the new getVarType2 in the new scanroutine}
begin
  result:=getVarType2;
end;

function TMainform.getScanStart: Dword;
begin
  try
    result:=strtoint('$'+FromAddress.text);
  except
    raise exception.Create('Invalid start address: '+FromAddress.text);
  end;
end;

procedure TMainform.setScanStart(newscanstart: dword);
begin
  FromAddress.text:=inttohex(newscanstart,8);
end;

function TMainform.getScanStop: Dword;
begin
  try
    result:=strtoint('$'+ToAddress.text);
  except
    raise exception.Create('Invalid stop address: '+ToAddress.text);
  end;
end;

procedure TMainform.setScanStop(newscanstop: dword);
begin
  ToAddress.text:=inttohex(newscanstop,8);
end;


function TMainform.getFastscan: boolean;
begin
  result:=cbFastscan.checked;
end;

procedure TMainform.setFastScan(state: boolean);
begin
  cbFastscan.checked:=state;
end;

function TMainform.getScanReadonly: boolean;
begin
  result:=Readonly.checked;
end;

procedure TMainform.setScanReadOnly(state: boolean);
begin
  readonly.checked:=state;
end;


function TMainform.GetRoundingType: TRoundingType;
{Property function to get the current rounding type}
begin
  result:=rtTruncated;
  if rt1.checked then result:=rtRounded else
  if rt2.checked then result:=rtExtremerounded else
  if rt3.Checked then result:=rtTruncated;
end;

procedure TMainform.SetRoundingType(rt: TRoundingType);
{Property function to set the current rounding type}
begin
  case rt of
    rtRounded:        rt1.checked;
    rtExtremerounded: rt2.checked;
    rtTruncated:      rt3.checked;
  end;
end;


procedure TMainform.setfoundcount(x: int64);
var
  xdouble: double;
begin
  ffoundcount:=x;
  xdouble:=x;
//  foundcountlabel.Caption:=inttostr(x);
  foundcountlabel.Caption:=Format('%.0n', [xdouble]);
end;

procedure TMainform.DestroyCancelButton;
begin
  if cancelbutton<>nil then freeandnil(cancelbutton);
  if cancelbuttonenabler<>nil then freeandnil(cancelbuttonenabler);
end;

procedure TMainform.SpawnCancelButton;
begin
  cancelbutton:=TButton.create(self);
  with cancelbutton do
  begin
    top:=newscan.top;
    left:=newscan.left;
    width:=(nextscanbutton.left+nextscanbutton.width)-left;
    height:=newscan.height;
    caption:='Cancel';
    onclick:=cancelbuttonclick;
    enabled:=false;
    tag:=0; //0=normal 1=force

    Hint:='This button will try to cancel the current scan. Click twice to force an exit';
    ParentShowHint:=false;
    ShowHint:=true;

    parent:=panel5;
  end;

  cancelbuttonenabler:=TTimer.create(self);

  with cancelbuttonenabler do
  begin
    interval:=2000; //2 seconds
    OnTimer:=cancelbuttonenablerinterval;
    enabled:=true;
    parent:=self;
  end;
end;


procedure TMainform.DisableGui;
{
This procedure will disable the gui. E.g while scanning the memory with no wait
screen.
}
var i: integer;
begin
  Groupbox1.Enabled:=false;
  for i:=0 to groupbox1.ControlCount-1 do
    groupbox1.Controls[i].Enabled:=false;
  
  scanvalue.Enabled:=false;
  if scanvalue2<>nil then
  begin
    scanvalue2.Enabled:=false;
    andlabel.Enabled:=false;
    scantext2.Enabled:=false;
  end;

  vartype.Enabled:=false;
  scantype.Enabled:=false;
  scantext.enabled:=false;
  label4.enabled:=false;
  label8.Enabled:=false;
  HexadecimalCheckbox.Enabled:=false;
  cbCaseSensitive.Enabled:=false;

  newscan.enabled:=false;
  nextscanbutton.enabled:=false;
  undoscan.enabled:=false;
end;

procedure TMainform.EnableGui(isnextscan: boolean);
{
Enables the gui options according to what type of scan is currently used
no scan, enable everything
already scanning, disable the group and type
}
var i: integer;
    fname,expectedfilename: string;
    scanstarted: boolean;
begin
  scanstarted:=newscan.caption=strnewscan;

  if not scanstarted then
  begin
    Groupbox1.Enabled:=true;
    for i:=0 to groupbox1.ControlCount-1 do
      groupbox1.Controls[i].Enabled:=true;
  end;

  scanvalue.Enabled:=true;
  if scanvalue2<>nil then
  begin
    scanvalue2.Enabled:=true;
    andlabel.Enabled:=true;
    scantext2.Enabled:=true;
  end;
  newscan.Enabled:=true;

  undoscan.Enabled:=isnextscan; //nextscan was already enabled
  nextscanbutton.Enabled:=scanstarted;
  vartype.Enabled:=not scanstarted;
  scantype.Enabled:=true;
  scantext.enabled:=true;
  label4.enabled:=true;
  label8.Enabled:=true;
  HexadecimalCheckbox.Enabled:=true;
  cbCaseSensitive.Enabled:=true;

  scanvalue.visible:=true;
  scantext.Visible:=true;

  Updatescantype;
  Scantype.ItemIndex:=0;

  //-----------------------
  //Get the expectedFilename
  //-----------------------
  SetExpectedTableName;

  cbspeedhack.enabled:=true;
  cbunrandomizer.Enabled:=true;


end;

procedure TMainform.toggleWindow;
resourcestring
  strWindowFailedToHide='A window failed to hide';
var c: integer;
begin
  togglewindows:=TTogglewindows.Create(false);
  c:=0;
  while togglewindows<>nil do
  begin
    if c=500 then
    begin
      togglewindows.free;
      raise exception.Create(strWindowFailedToHide);
    end;
    sleep(10);
    inc(c);
  end;
end;

procedure TMainForm.ReserveMem;
var before: integer;
    i: integer;
begin
  before:=length(memrec);

  if numberofrecords<before then
  begin
    //cleanup some extra memory
    for i:=numberofrecords to before-1 do
    begin
      setlength(memrec[i].pointers,0);
      setlength(memrec[i].allocs,0);
    end;
  end;

  setlength(memrec,numberofrecords);
  setlength(frozenfvalue,numberofrecords);
  setlength(frozenStrings,numberofrecords);
  setlength(frozenbytes,NumberOfRecords);
  setlength(selected,numberofrecords);
  setlength(hotkeystrings,NumberOfRecords);
  setlength(Hotkeys,numberofrecords);

  if numberofrecords>before then
  begin
    //initialize the new memory
    for i:=before to numberofrecords-1 do
    begin
      zeromemory(@memrec[i],sizeof(memrec[i]));
      zeromemory(@frozenfvalue[i],sizeof(frozenfvalue[i]));
      zeromemory(@frozenStrings[i],sizeof(frozenStrings[i]));
      zeromemory(@frozenbytes[i],sizeof(frozenbytes[i]));
      zeromemory(@selected[i],sizeof(selected[i]));
      zeromemory(@hotkeystrings[i],sizeof(hotkeystrings[i]));
      zeromemory(@Hotkeys[i],sizeof(Hotkeys[i]));
    end;
  end;
end;


procedure TMainform.exceptionhandler(Sender: TObject; E: Exception);
begin
  if (E.Message='Error creating window device context') then exit;
  screen.Cursor:=crdefault;
  closefile(addressfile);
  closefile(memoryfile);
  closefile(newAddressfile);
  closefile(newmemoryfile);
  Application.ShowException(E);
end;

procedure TMainForm.freedebugger;
begin
  //the debugger says the process has ended, or the thread has stopped
  freeandnil(debuggerthread);
  advancedoptions.Pausebutton.Down:=false;
end;


procedure TMainform.SetReadWriteBreakpoint(address: dword; size: dword);
var mbi: _Memory_Basic_Information;
    i: integer;
    ct: _context;
    regsinuse: integer;
    originaladdress,originalsize: dword;
    dr: dword;

procedure Set4bytebreak;
begin
  case regsinuse of
    0: begin
         ct.dr0:=address;
         ct.dr7:=ct.dr7 or reg0set or reg0rw or debugexact or reg0len4;
       end;

    1: begin
         ct.dr1:=address;
         ct.dr7:=ct.Dr7 or reg1set or reg1rw or debugexact or reg1len4;
       end;

    2: begin
         ct.Dr2:=address;
         ct.dr7:=ct.dr7 or reg2set or reg2rw or debugexact or reg2len4;
       end;

    3: begin
         ct.Dr3:=address;
         ct.dr7:=ct.dr7 or reg3set or reg3rw or debugexact or reg3len4;
       end;
  end;

  inc(address,4);
  dec(size,4);
  inc(regsinuse);
end;

procedure Set2bytebreak;
begin
  case regsinuse of
    0: begin
         ct.dr0:=address;
         ct.dr7:=ct.dr7 or reg0set or reg0rw or debugexact or reg0len2;
       end;

    1: begin
         ct.dr1:=address;
         ct.dr7:=ct.Dr7 or reg1set or reg1rw or debugexact or reg1len2;
       end;

    2: begin
         ct.Dr2:=address;
         ct.dr7:=ct.dr7 or reg2set or reg2rw or debugexact or reg2len2;
       end;

    3: begin
         ct.Dr3:=address;
         ct.dr7:=ct.dr7 or reg3set or reg3rw or debugexact or reg3len2;
       end;
  end;

  inc(address,2);
  dec(size,2);
  inc(regsinuse);
end;

procedure Set1bytebreak;
begin
  case regsinuse of
    0: begin
         ct.dr0:=address;
         ct.dr7:=ct.dr7 or reg0set or reg0rw or debugexact;
       end;

    1: begin
         ct.dr1:=address;
         ct.dr7:=ct.Dr7 or reg1set or reg1rw or debugexact;
       end;

    2: begin
         ct.Dr2:=address;
         ct.dr7:=ct.dr7 or reg2set or reg2rw or debugexact;
       end;

    3: begin
         ct.Dr3:=address;
         ct.dr7:=ct.dr7 or reg3set or reg3rw or debugexact;
       end;
  end;

  inc(address);
  dec(size);
  inc(regsinuse);
end;

resourcestring
  strAccessed='The following opcodes accessed the selected address';

var rd: dword;
    tmp: byte;
    ths: thandle;
    th: thandle;
    tE: threadentry32;
begin
  //check if you can read address to address+size
  if not (formsettings.rbDebugRegisters.checked or formsettings.cbKDebug.checked) then
  begin
    readprocessmemory(processhandle,pointer(address),@tmp,1,rd);
    if rd<>1 then raise exception.Create(strAddressHasToBeReadable);
  end;

  if foundcodedialog<>nil then raise exception.Create('The debugger is already trying to find out what reads,writes or accesses a certain address. First close the other window');
 
  if (formsettings.cbKdebug.checked) and (debuggerthread=nil) and (not KDebugger.isActive) then
    KDebugger.startDebugger; //start the kerneldebugger

  foundcodedialog:=TFoundcodedialog.create(self);
  foundcodedialog.Caption:=strAccessed;
  foundcodedialog.btnOK.caption:=strStop;

  originaladdress:=address;
  originalsize:=size;
  zeromemory(@ct,sizeof(ct));
  ct.ContextFlags:=CONTEXT_DEBUG_REGISTERS;

  //configure the debugregs
  if formsettings.rbDebugRegisters.checked or formsettings.cbKDebug.checked then
  begin
    foundcodedialog.useexceptions:=false;
    regsinuse:=0;
    ct.dr7:=0;
    while (regsinuse<4) and (size>0) do
    begin
      if size>=4 then
      begin
        if (address mod 4)>0 then
        begin
          if (address mod 2)>0 then
          begin
            set1bytebreak; //watch on a byte
            continue;
          end
          else
          begin
            set2bytebreak;
            continue;
          end;
        end
        else
        begin
          set4bytebreak;
          continue;
        end;
      end;

      if size>=2 then
      begin
        if (address mod 2)>0 then
        begin
          set1bytebreak; //watch on a byte
          continue;
        end
        else
        begin
          set2bytebreak;
          continue;
        end;
      end;


      if size=1 then
        set1bytebreak;
    end;

    //ct.dr7:=$D0303;
    if formsettings.cbKdebug.Checked and (debuggerthread=nil) then
    begin
      KDebugger.SetBreakpoint(originaladdress, bt_OnReadsAndWrites, originalsize, bo_findcode);
    end
    else
    begin
      debuggerthread.DRRegs:=ct;

      debuggerthread.Suspend;
      for i:=0 to length(debuggerthread.threadlist)-1 do
      begin
        suspendthread(debuggerthread.threadlist[i][1]);
        SetThreadContext(debuggerthread.threadlist[i][1],debuggerthread.DRRegs);
        resumethread(debuggerthread.threadlist[i][1]);
      end;

      debuggerthread.FindWriter2:=true;
      debuggerthread.Resume;
    end;
  end
  else
  begin
   //dont use debug regs
    foundcodedialog.useexceptions:=true;
    virtualqueryEx(processhandle,pointer(address),mbi,sizeof(mbi));

    debugger.DebuggerThread.findreader.pagebase:=dword(mbi.BaseAddress);
    debugger.DebuggerThread.findreader.pagesize:=dword(mbi.RegionSize);
    debugger.DebuggerThread.findreader.Address:=address;
    debugger.DebuggerThread.findreader.size:=size;
    DebuggerThread.findreaderset:=true;
    DebuggerThread.alsowrites:=true;

    VirtualProtectEx(processhandle,pointer(address),size,PAGE_NOACCESS,debugger.DebuggerThread.findreader.originalprotection);
  end;

  foundcodedialog.show;
end;


procedure TMainform.SetReadBreakpoint(address: dword; size: dword);
var mbi: _Memory_Basic_Information;
    i: integer;
    tmp:byte;
    rD:dword;
resourcestring strOpcodeRead='The following opcodes read from the selected address';
begin
  readprocessmemory(processhandle,pointer(address),@tmp,1,rd);
  if rd<>1 then raise exception.Create(strAddressHasToBeReadable);

  if foundcodedialog<>nil then raise exception.Create('The debugger is already trying to find out what reads,writes or accesses a certain address. First close the other window');

  foundcodedialog:=TFoundcodedialog.create(self);
  foundcodedialog.Caption:=strOpcodeRead;
  foundcodedialog.useexceptions:=true;
  foundcodedialog.btnOK.caption:=strStop;

  virtualqueryEx(processhandle,pointer(address),mbi,sizeof(mbi));

  debugger.DebuggerThread.findreader.pagebase:=dword(mbi.BaseAddress);
  debugger.DebuggerThread.findreader.pagesize:=dword(mbi.RegionSize);
  debugger.DebuggerThread.findreader.Address:=address;
  debugger.DebuggerThread.findreader.size:=size;
  DebuggerThread.findreaderset:=true;

  VirtualProtectEx(processhandle,pointer(address),size,PAGE_NOACCESS,debugger.DebuggerThread.findreader.originalprotection);
  foundcodedialog.show;
end;

procedure TMainform.SetWriteBreakpoint(address: dword; size: dword);
var mbi: _Memory_Basic_Information;
    i: integer;
    ct: _context;
    regsinuse: integer;
    originaladdress,originalsize: dword;
    dr: dword;

procedure Set4bytebreak;
begin
  case regsinuse of
    0: begin
         ct.dr0:=address;
         ct.dr7:=ct.dr7 or reg0set or reg0w or debugexact or reg0len4;
       end;

    1: begin
         ct.dr1:=address;
         ct.dr7:=ct.Dr7 or reg1set or reg1w or debugexact or reg1len4;
       end;

    2: begin
         ct.Dr2:=address;
         ct.dr7:=ct.dr7 or reg2set or reg2w or debugexact or reg2len4;
       end;

    3: begin
         ct.Dr3:=address;
         ct.dr7:=ct.dr7 or reg3set or reg3w or debugexact or reg3len4;
       end;
  end;

  inc(address,4);
  dec(size,4);
  inc(regsinuse);
end;

procedure Set2bytebreak;
begin
  case regsinuse of
    0: begin
         ct.dr0:=address;
         ct.dr7:=ct.dr7 or reg0set or reg0w or debugexact or reg0len2;
       end;

    1: begin
         ct.dr1:=address;
         ct.dr7:=ct.Dr7 or reg1set or reg1w or debugexact or reg1len2;
       end;

    2: begin
         ct.Dr2:=address;
         ct.dr7:=ct.dr7 or reg2set or reg2w or debugexact or reg2len2;
       end;

    3: begin
         ct.Dr3:=address;
         ct.dr7:=ct.dr7 or reg3set or reg3w or debugexact or reg3len2;
       end;
  end;

  inc(address,2);
  dec(size,2);
  inc(regsinuse);
end;

procedure Set1bytebreak;
begin
  case regsinuse of
    0: begin
         ct.dr0:=address;
         ct.dr7:=ct.dr7 or reg0set or reg0w or debugexact;
       end;

    1: begin
         ct.dr1:=address;
         ct.dr7:=ct.Dr7 or reg1set or reg1w or debugexact;
       end;

    2: begin
         ct.Dr2:=address;
         ct.dr7:=ct.dr7 or reg2set or reg2w or debugexact;
       end;

    3: begin
         ct.Dr3:=address;
         ct.dr7:=ct.dr7 or reg3set or reg3w or debugexact;
       end;
  end;

  inc(address);
  dec(size);
  inc(regsinuse);
end;

var rd: dword;
    tmp: byte;
resourcestring strOpcodeChanged='The following opcodes changed the selected address';
begin
  //check if you can read address to address+size
  if not (formsettings.rbDebugRegisters.checked or formsettings.cbKDebug.checked) then
  begin
    readprocessmemory(processhandle,pointer(address),@tmp,1,rd);
    if rd<>1 then raise exception.Create(strAddressHasToBeReadable);
  end;

  if foundcodedialog<>nil then raise exception.Create('The debugger is already trying to find out what reads,writes or accesses a certain address. First close the other window');

  if (formsettings.cbKdebug.checked) and (debuggerthread=nil) and (not KDebugger.isActive) then
    KDebugger.startDebugger;

  foundcodedialog:=TFoundcodedialog.create(self);
  foundcodedialog.Caption:=strOpcodeChanged;
  foundcodedialog.btnOK.caption:=strstop;    

  originaladdress:=address;
  originalsize:=size;
  zeromemory(@ct,sizeof(ct));
  ct.ContextFlags:=CONTEXT_DEBUG_REGISTERS;

  if formsettings.rbDebugRegisters.checked then
  begin
    foundcodedialog.useexceptions:=false;
    regsinuse:=0;
    ct.dr7:=0;
    while (regsinuse<4) and (size>0) do
    begin
      if size>=4 then
      begin
        if (address mod 4)>0 then
        begin
          if (address mod 2)>0 then
          begin
            set1bytebreak; //watch on a byte
            continue;
          end
          else
          begin
            set2bytebreak;
            continue;
          end;
        end
        else
        begin
          set4bytebreak;
          continue;
        end;
      end;

      if size>=2 then
      begin
        if (address mod 2)>0 then
        begin
          set1bytebreak; //watch on a byte
          continue;
        end
        else
        begin
          set2bytebreak;
          continue;
        end;
      end;


      if size=1 then
        set1bytebreak;
    end;

   // ct.dr7:=$D0303;
    if formsettings.cbKdebug.Checked and (debuggerthread=nil) then
    begin
      KDebugger.SetBreakpoint(originaladdress, bt_OnWrites, originalsize, bo_findcode);
    end
    else
    begin
      debuggerthread.DRRegs:=ct;

      debuggerthread.Suspend;
      for i:=0 to length(debuggerthread.threadlist)-1 do
      begin
        suspendthread(debuggerthread.threadlist[i][1]);
        SetThreadContext(debuggerthread.threadlist[i][1],debuggerthread.DRRegs);
        resumethread(debuggerthread.threadlist[i][1]);
      end;

      debuggerthread.FindWriter2:=true;
      debuggerthread.Resume;
    end;
  end
  else
  begin
    foundcodedialog.useexceptions:=true;
    virtualqueryEx(processhandle,pointer(originaladdress),mbi,sizeof(mbi));

    debugger.DebuggerThread.readonly.pagebase:=dword(mbi.BaseAddress);
    debugger.DebuggerThread.readonly.pagesize:=dword(mbi.RegionSize);
    debugger.DebuggerThread.readonly.Address:=originaladdress;
    debugger.DebuggerThread.readonly.size:=originalsize;
    DebuggerThread.readonlyset:=true;

    VirtualProtectEx(processhandle,pointer(originaladdress),originalsize,PAGE_EXECUTE_READ,debugger.DebuggerThread.readonly.originalprotection);
  end;



  foundcodedialog.show;
end;

procedure TMainform.Deletegroups(groups: grouptype);
var i: integer;
begin
  for i:=0 to numberofrecords-1 do
  begin
    if groups[1] and (memrec[i].Group=1) then selected[i]:=true else
    if groups[2] and (memrec[i].Group=2) then selected[i]:=true else
    if groups[3] and (memrec[i].Group=3) then selected[i]:=true else
    if groups[4] and (memrec[i].Group=4) then selected[i]:=true else
    if groups[5] and (memrec[i].Group=5) then selected[i]:=true else
    if groups[6] and (memrec[i].Group=6) then selected[i]:=true else

    selected[i]:=false;
  end;

  deleterecords;
end;


procedure TMainForm.DeleteRecords;
var i,j: Integer;
begin
  if editingscript then exit; //don't do it when editing a script

  i:=0;
  while i<numberofrecords do
  begin
    if selected[i] then
    begin
      unregisterhotkey(handle,hotkeys[i]);
      hotkeys[i]:=-1;
      setlength(frozenbytes[i],0);

      for j:=i to numberofrecords-2 do
      begin
        memrec[j]:=memrec[j+1];
        frozenfvalue[j]:=frozenfvalue[j+1];
        frozenstrings[j]:=frozenstrings[j+1];
        frozenbytes[j]:=frozenbytes[j+1];
        selected[j]:=selected[j+1];
        hotkeystrings[j]:=hotkeystrings[j+1];
        hotkeys[j]:=hotkeys[j+1];
      end;

      dec(numberofrecords);
      dec(i);
      reservemem;

      if firstshiftselected>numberofrecords-1 then firstshiftselected:=-1;
    end;

    inc(i);
  end;

  If lastselected>numberofrecords-1 then lastselected:=numberofrecords-1;
  if lastselected>-1 then selected[lastselected]:=true;
  Updatescreen;
  Updatelist;
end;


Procedure TMainForm.UpdateScreen;
var rec,i,j: Integer;
    temp:string;
    col: tcolor;
    realaddress,realaddress2,count:dword;
    error: boolean;
    check: boolean;

resourcestring
  strAllowNegative='Allow negative changes';
  strAllowPositive='Allow positive changes';
  strNormalFreeze='Don''t allow any change';


begin
  if numberofrecords>=numberoflines then
  begin
    if not scrollbar1.Enabled then
      scrollbar1.enabled:=true;

    try
      //sometimes on resolion changes this causes a problem, so in a try except to try and fix it on error
      if scrollbar1.max<>numberofrecords-1 then
        scrollbar1.max:=numberofrecords-1;

      if scrollbar1.PageSize<>numberoflines-1 then
        scrollbar1.pagesize:=numberoflines-1;

      if scrollbar1.LargeChange<>numberoflines-1 then
        scrollbar1.LargeChange:=numberoflines-1;

    except
      try
        scrollbar1.Position:=0;
        scrollbar1.max:=numberofrecords-1;
        scrollbar1.PageSize:=numberoflines-1;
        scrollbar1.LargeChange:=numberoflines-1;
      except

      end;
    end;

  end else
  begin
    try
      if scrollbar1.Enabled then
        scrollbar1.enabled:=false;

      if scrollbar1.Position<>0 then
        scrollbar1.position:=0;
    except
      
    end;
  end;

  for i:=0 to numberoflines-1 do
  begin
    rec:=scrollbar1.Position+i;
    if rec<numberofrecords then
    begin
      if ((memrec[rec].Frozen) or (hotkeys[rec]<>-1)) and (memrec[rec].VarType in [0,1,2,3,4,6]) then
      begin
        case memrec[rec].Frozendirection of
          0:
          begin
            col:=clBlue;
            temp:='=';
          end;

          1:
          begin
            temp:='-';
            col:=clRed;
          end;

          2:
          begin
            temp:='+';
            col:=clGreen;
          end;
        end;

        if selected[rec] then col:=ClWhite;

        if freezedirection[i].Font.Color<>col then
          freezedirection[i].Font.Color:=col;

        if temp<>freezedirection[i].Caption then
        begin
          freezedirection[i].Caption:=temp;

          if temp='-' then freezedirection[i].Hint:=strAllowNegative;//'Allow negative changes';
          if temp='+' then freezedirection[i].Hint:=strAllowPositive;//'Allow positive changes';
          if temp='=' then freezedirection[i].Hint:=strNormalFreeze; //'Don''t allow any change';
          freezedirection[i].ShowHint:=true;
        end;



        freezedirection[i].visible:=true;
      end
      else
      begin
        freezedirection[i].visible:=false;
      end;

      frozenbox[i].checked:=memrec[rec].Frozen;
      if hotkeys[rec]<>-1 then
        frozenbox[i].Enabled:=false
      else
        frozenbox[i].Enabled:=true;

      description[i].Caption:=memrec[rec].Description;


      if memrec[rec].IsPointer then
      begin
        error:=false;

        //find the real address
        realaddress2:=memrec[rec].pointers[length(memrec[rec].pointers)-1].Address;
        for j:=length(memrec[rec].pointers)-1 downto 0 do
        begin
          check:=(readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count));
          if check and (count=4) then
            realaddress2:=realaddress+memrec[rec].pointers[j].offset
          else
          begin
            error:=true;
            break;
          end;
        end;
        realaddress:=realaddress2;

        if not error then
          address[i].Caption:='P->'+IntToHex(realaddress,8)
        else
          address[i].Caption:='P->????????';
      end
      else
        address[i].caption:=IntTohex(memrec[rec].address,8);


     // if not frozenbox[i].visible then  //if it's not yet visible, make it visible
      begin
        frozenbox[i].visible:=true;
        description[i].visible:=true;

        if memrec[rec].VarType<>255 then
        begin
          address[i].visible:=true;
          valtype[i].visible:=true;

        end
        else
        begin
          address[i].visible:=false;
          valtype[i].visible:=false;
//          value[i].visible:=false;
        end;
        value[i].visible:=true;
      end;

      case memrec[rec].vartype of
      0         : valtype[i].Caption:=vartype.Items[1]; //byte
      1         : valtype[i].Caption:=vartype.Items[2];
      2         : valtype[i].Caption:=vartype.Items[3];
      3         : valtype[i].caption:=vartype.Items[5];
      4         : valtype[i].caption:=vartype.Items[6];
      5         : begin
                    valtype[i].Caption:=vartype.Items[0]+'['+IntToStr(memrec[rec].Bitlength)+']';
                    address[i].caption:=address[i].caption+'^'+IntToStr(memrec[rec].Bit);
                  end;
      6         : valtype[i].caption:=vartype.Items[4];
      7         :
                  begin
                    if memrec[rec].unicode then
                      valtype[i].Caption:='U'+vartype.Items[7]+'['+inttostr(memrec[rec].Bit)+']'
                    else
                      valtype[i].Caption:=vartype.Items[7]+'['+inttostr(memrec[rec].Bit)+']';
                  end;
      8         : valtype[i].Caption:=vartype.Items[8]+'['+inttostr(memrec[rec].Bit)+']';

      255       : valtype[i].Caption:=strAutoAssemble;
      else      valtype[i].caption:=strBUG;
      end;



      if selected[rec] then
      begin
        if lastselected=rec then
        begin
          select[i].Color:=clActiveCaption;
          select[i].Font.Color:=clActiveCaption;
          Frozenbox[i].Color:=clActiveCaption;
        end
        else
        begin
          select[i].Color:=clGradientActiveCaption;
          select[i].Font.Color:=clGradientActiveCaption;
          Frozenbox[i].Color:=clGradientActiveCaption;
        end;
        description[i].Font.Color:=clHighlightText;
        address[i].Font.Color:=clHighlightText;
        valtype[i].Font.Color:=clHighlightText;
        value[i].Font.Color:=clHighlightText;
      end
      else
      begin
        case memrec[rec].Group of
          0  :  begin
                  description[i].Font.Color:=clWindowText;
                  address[i].Font.Color:=clWindowText;
                  valtype[i].Font.Color:=clWindowText;
                  value[i].Font.Color:=clWindowText;
                end;

          1  :  begin
                  description[i].Font.Color:=clRed;
                  address[i].Font.Color:=clRed;
                  valtype[i].Font.Color:=clRed;
                  value[i].Font.Color:=clRed;
                end;

          2  :  begin
                  description[i].Font.Color:=clBlue;
                  address[i].Font.Color:=clBlue;
                  valtype[i].Font.Color:=clBlue;
                  value[i].Font.Color:=clBlue;
                end;

          3  :  begin
                  description[i].Font.Color:=clYellow;
                  address[i].Font.Color:=clYellow;
                  valtype[i].Font.Color:=clYellow;
                  value[i].Font.Color:=clYellow;
                end;

          4  :  begin
                  description[i].Font.Color:=clGreen;
                  address[i].Font.Color:=clGreen;
                  valtype[i].Font.Color:=clGreen;
                  value[i].Font.Color:=clGreen;
                end;

          5  :  begin
                  description[i].Font.Color:=clPurple;
                  address[i].Font.Color:=clPurple;
                  valtype[i].Font.Color:=clPurple;
                  value[i].Font.Color:=clPurple;
                end;

          6  :  begin
                  description[i].Font.Color:=clWhite;
                  address[i].Font.Color:=clWhite;
                  valtype[i].Font.Color:=clWhite;
                  value[i].Font.Color:=clWhite;
                end;

          else  begin
                  description[i].Font.Color:=clWindowText;
                  address[i].Font.Color:=clWindowText;
                  valtype[i].Font.Color:=clWindowText;
                  value[i].Font.Color:=clWindowText;
                end;
        end;

        select[i].Color:=clBtnFace;
        select[i].Font.Color:=clBtnFace;
        Frozenbox[i].Color:=clBtnFace;
      end;
    end else
    begin
      description[i].Font.Color:=clBtnFace;
      select[i].Color:=clBtnFace;
      select[i].Font.Color:=clBtnFace;
      description[i].Font.Color:=clBtnFace;
      Frozenbox[i].Color:=clBtnFace;
      address[i].Font.Color:=clBtnFace;
      valtype[i].Font.Color:=clBtnFace;
      value[i].Font.Color:=clBtnFace;

      if frozenbox[i].visible then
      begin
        frozenbox[i].visible:=false;
        description[i].visible:=false;
        address[i].visible:=false;
        valtype[i].visible:=false;
        value[i].visible:=false;
        freezedirection[i].Visible:=false;
      end;

    end;
  end;



end;

function TMainForm.CheckIfSaved: boolean;
resourcestring strAskToSave='You haven''t saved your last changes yet. Save Now?';
var help :word;
    i,j: Integer;
begin
  //result:=true;
  result:=not editedsincelastsave;

  if advancedoptions.codelist2.items.Count=oldcodelistcount then
  begin
    

  end else result:=false;

  if (OldNumberOfRecords=NumberOfRecords) then
  begin
    i:=0;
    while (result) and (i<numberofrecords) do
    begin
      if oldmemrec[i].Description<>memrec[i].Description then result:=false;
      if oldmemrec[i].Address<>memrec[i].Address then result:=false;
      if oldmemrec[i].VarType<>memrec[i].VarType then result:=false;
      if oldmemrec[i].Bit<>memrec[i].Bit then result:=false;
      if oldmemrec[i].bitlength<>memrec[i].bitlength then result:=false;
      if length(oldmemrec[i].pointers)<>length(memrec[i].pointers) then result:=false else
      begin
        for j:=0 to length(oldmemrec[i].pointers)-1 do
        begin
          if oldmemrec[i].pointers[j].Address<>memrec[i].pointers[j].Address then result:=false;
          if oldmemrec[i].pointers[j].offset<>memrec[i].pointers[j].Offset then result:=false;
        end;
      end;
      if oldmemrec[i].Group<>memrec[i].Group then result:=false;

      inc(i);
    end;
  end else result:=false;

  if not (oldcomments=comments.memo1.Text) then result:=false;


  if itemshavechanged then result:=false;
  
  if result=false then
  begin
    help:=messagedlg(strAskToSave,mtConfirmation,mbYesNoCancel,0);
    case help of
      mrCancel      : result:=false;
      mrYes         : begin
                        result:=true;
                        SaveButton.click;
                      end;
    else result:=true;
    end;
  end;
end;

procedure TMainForm.UpdateScanType;
var OldText: String;
    OldIndex: Integer;
    hexvis: boolean;
    floatvis: boolean;
    oldwidth: integer;
    i: integer;
resourcestring
  strScantextcaptiontotext='Text:';
  strScantextcaptiontoValue='Value:';
  strsearchForText='Search for text';
  strSearchForArray='Search for this array';
begin


  OldIndex:=Scantype.itemindex;
  OldText:=Scantype.text;
  hexvis:=true;
  floatvis:=false;

  ScanType.Items.Clear;

  ScanText.Caption:=strScantextcaptiontoValue;
  case varType.ItemIndex of
    0   :     begin
                ScanType.Items.Add(strExact);
                ScanType.DropDownCount:=1;
              end;

  1,2,3,4,5,6,9:begin  //byte-word-dword--8bytes-float-double-all
                if vartype.itemindex in [5,6,9] then
                begin
                  if oldindex=0 then
                    floatvis:=true;

                  if vartype.itemindex=9 then
                    hexvis:=false;
                end;

                ScanType.Items.Add(strExactValue);
                ScanType.Items.Add(strBiggerThan);
                ScanType.Items.Add(strsmallerThan);
                ScanType.Items.Add(strValueBetween);

                if NextScanbutton.Enabled then
                begin
                  scantype.Items.Add(strIncreasedValue);
                  Scantype.Items.Add(strIncreasedValueBy);
                  ScanType.Items.Add(strDecreasedValue);
                  ScanType.Items.Add(strDecreasedValueBy);
                  ScanType.Items.add(strChangedValue);
                  ScanType.Items.Add(strUnchangedValue);

                  if (not advanced) and (not cbfasterscan.checked) then
                  begin
                    ScanType.Items.Add(strSameAsFirstScan);
                    Scantype.DropDownCount:=11;
                  end
                  else
                    Scantype.DropDownCount:=10;

                end else
                begin
                  ScanType.Items.Add(strUnknownInitialValue);
                  ScanType.DropDownCount:=5;
                end;
              end;

  7:          begin  //text
                ScanText.caption:=strScanTextCaptionToText;
                ScanType.Items.Add(strSearchForText);
                //perhaps also a changed value and unchanged value scan
                ScanType.DropDownCount:=1;
                hexvis:=false;
              end;

  8:          begin  //array of bytes
                ScanText.caption:=vartype.Items[8];
                ScanType.Items.Add(strSearchforarray);
                ScanType.DropDownCount:=1;
              end;

  10:         begin
                //custom
                //go through the list of custom scan's
                for i:=0 to length(CustomScanScripts)-1 do
                  scantype.Items.Add(CustomScanScripts[i].name);

                ScanType.DropDownCount:=length(CustomScanScripts);
              end;
  end;

  if varType.ItemIndex = 10 then  //custom scan
  begin
    //CreateCustomScanButton: TButton;
    //EditCustomScanButton: TButton;

    if CreateCustomScanButton=nil then
    begin
      //spawn it
      CreateCustomScanButton:=TButton.Create(self);
      with CreateCustomScanButton do
      begin
        width:=50;
        height:=19;
        left:=ScanType.left+ScanType.Width+3;
        top:=ScanType.Top+(scantype.Height div 2)-(height div 2);

        anchors:=[akTop,akRight];
        caption:='New';
        parent:=self;
        onclick:=CreateCustomScanButtonClick;
      end;

      EditCustomScanButton:=TButton.Create(self);
      with EditCustomScanButton do
      begin
        width:=50;
        height:=19;
        left:=CreateCustomScanButton.left+CreateCustomScanButton.Width+3;
        top:=CreateCustomScanButton.Top;

        anchors:=[akTop,akRight];
        caption:='Edit';
        parent:=self;
        onclick:=EditCustomScanButtonClick;
      end;
    end;
  end
  else
  begin

    if CreateCustomScanButton<>nil then //free it
    begin

      freeandnil(CreateCustomScanButton);

      if EditCustomScanButton<>nil then
        freeandnil(EditCustomScanButton);
    end;


  end;

  if (oldtext=strUnknownInitialValue) and (NextScanButton.enabled) then scantype.itemindex:=0 else scantype.itemindex:=oldindex;

  if (scantype.text=strIncreasedValueBy) or (scantype.text=strDecreasedValueBy) then
  begin
    if cbpercentage=nil then
    begin
      cbpercentage:=tcheckbox.create(self);
      cbpercentage.Left:=scantype.Left+scantype.Width+5;
      cbpercentage.Top:=scantype.Top+2;
      cbpercentage.Caption:='at least xx%';
      cbpercentage.Anchors:=[akTop,akRight];
      cbpercentage.Width:=80;
      cbpercentage.Parent:=scantype.Parent;
    end;
  end
  else
  begin
    if cbpercentage<>nil then
      freeandnil(cbpercentage);
  end;

  if scantype.Text=strValueBetween then
  begin
    if scanvalue2=nil then
    begin
      //decrease the width of the scanvalue editbox
      oldwidth:=scanvalue.width;
      scanvalue.Width:=(scanvalue.Width div 2)-20;

      //create a 2nd editbox
      scanvalue2:=tedit.create(self);
      //scanvalue2.onkeydown:=scanvalueKeyDown;
      scanvalue2.OnKeyPress:=ScanvalueoldKeyPress;
      scanvalue2.PopupMenu:=ccpmenu;
      scanvalue2.Left:=scanvalue.left+scanvalue.Width+20;
      scanvalue2.Width:=oldwidth-scanvalue.width-20;
      scanvalue2.Top:=scanvalue.top;
      scanvalue2.Parent:=scanvalue.Parent;
      scanvalue2.Anchors:=scanvalue.Anchors;
      scanvalue2.TabOrder:=scanvalue.TabOrder+1;
      scanvalue2.Text:=oldscanvalue2text;

      scantext2:=tlabel.create(self);
      scantext2.caption:=scantext.caption;
      scantext2.Left:=scanvalue2.Left;
      scantext2.Top:=scantext.top;
      scantext2.Parent:=scantext.parent;
      scantext2.Anchors:=scantext.Anchors;

      andlabel:=tlabel.Create(self);
      andlabel.Caption:='and';
      andlabel.Left:=scanvalue2.Left-20;
      andlabel.Top:=scanvalue2.Top+2;
      andlabel.Parent:=scanvalue2.Parent;
      andlabel.Anchors:=scantext.Anchors;
    end
  end else
  begin
    if scanvalue2<>nil then
    begin
      scanvalue.Width:=scanvalue.width+20+scanvalue2.width;
      oldscanvalue2text:=scanvalue2.Text;
      freeandnil(scanvalue2);
      freeandnil(scantext2);
      freeandnil(andlabel);
    end;
  end;


  if (scantype.Text=strIncreasedValue) or
     (scantype.text=strDecreasedValue) or
     (scantype.Text=strChangedValue) or
     (scantype.Text=strUnchangedValue) or
     (scantype.Text=strUnknownInitialValue) or
     (scantype.Text=strSameAsFirstScan)
     then
     begin
       Scantext.Visible:=false;
       Scanvalue.visible:=false;
       HexadecimalCheckbox.visible:=false;
     end else
     begin
       Scantext.Visible:=true;
       Scanvalue.visible:=true;
       HexadecimalCheckbox.visible:=hexvis;
     end;

  pnlfloat.Visible:=floatvis;

end;


function TMainform.getStringFromRecord(itemid: Integer):string;
var i,j,k: Integer;
    read1: byte;
    read2: word;
    read3: dword;
    read4: single;
    read5: double;
    read6: Int64;
    read7: pchar;
    read72: pwidechar;
    read8: array of byte;
    read9: pbyte;

    count: dword;
    rec: Integer;
    temp,temp2: string;

    nrofbytes: integer;

    realaddress,realaddress2: dword;
    stopnow: boolean;
    check: boolean;

begin
  rec:=itemid;
  if not memrec[rec].frozen then
  begin
    if memrec[rec].IsPointer then
    begin
      //find the real address
      realaddress2:=memrec[rec].pointers[length(memrec[rec].pointers)-1].Address;
      for j:=length(memrec[rec].pointers)-1 downto 0 do
      begin

        check:=readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count);
        if check and (count=4) then
          realaddress2:=realaddress+memrec[rec].pointers[j].offset
        else
        begin
          result:='??';
          exit;
        end;

      end;

      realaddress:=realaddress2;
    end else realaddress:=memrec[rec].Address;


  //get the value!!!


    case memrec[rec].VarType of
    0:            begin //byte
                    check:=readprocessmemory(processhandle,pointer(realaddress),addr(read1),1,count);
                    if (not check) or (count=0) then result:='??' else
                      begin
                        if memrec[rec].ShowAsHex then
                          result:='0x'+IntToHex(read1,2)
                        else
                        if formsettings.cbShowAsSigned.checked then result:=IntToStr(ShortInt(read1))
                        else result:=IntToStr(read1);
                      end;
                  end;

    1:            begin //word
                    check:=readprocessmemory(processhandle,pointer(realaddress),addr(read2),2,count);
                    if (not check) or (count=0) then result:='??' else
                      begin
                        if memrec[rec].ShowAsHex then
                          result:='0x'+IntToHex(read2,4)
                        else
                        if formsettings.cbShowAsSigned.checked then result:=IntToStr(SmallInt(read2))
                        else result:=IntToStr(read2);
                      end;
                  end;

    2:            begin //dword
                    read3:=0;
                    check:=readprocessmemory(processhandle,pointer(realaddress),addr(read3),4,count);

                    if (not check) or (count=0) then result:='??' else
                      begin
                        if memrec[rec].ShowAsHex then
                          result:='0x'+IntToHex(read3,8)
                        else
                        if formsettings.cbShowAsSigned.checked then result:=IntToStr(Longint(read3))
                        else result:=IntToStr(read3);
                      end;
                  end;

    3:            begin //float
                    check:=readprocessmemory(processhandle,pointer(realaddress),addr(read4),4,count);
                    if (not check) or (count=0) then result:='??' else
                      result:=FloatToStr(read4);
                  end;

    4:            begin  //double
                    check:=readprocessmemory(processhandle,pointer(realaddress),addr(read5),8,count);
                    if (not check) or (count=0) then result:='??' else
                      result:=FloatToStr(read5);
                  end;

    5:            begin //binary
                    //read the bytes

                    nrofbytes:=1+((memrec[rec].Bit+memrec[rec].bitlength) div 8);
                    setlength(read8,nrofbytes);

                    check:=readprocessmemory(processhandle,pointer(realaddress),addr(read8[0]),nrofbytes,count);
                    if (not check) or (count=0) then result:='??' else
                    begin
                      //convert what i need to a string of bits
                      temp:='';
                      j:=memrec[rec].Bit;
                      read9:=@read8[0];
                      for k:=1 to memrec[rec].bitlength do
                      begin
                        temp:=temp+IntToStr(getbit(j,read9^));
                        inc(j);
                        if j>=8 then
                        begin
                          j:=0;
                          inc(read9);
                        end;
                      end;

                      temp2:='';
                      for k:=length(temp) downto 1 do
                        temp2:=temp2+temp[k];

                      if formsettings.cbBinariesAsDecimal.checked then
                      begin
                        try
                          result:=IntToStr(bintoint(temp2));
                        except
                          result:=strtoolong;
                        end;
                      end else result:=temp2;

                      //and convert them to a decimal value
                    end;
                  end;

    6:            begin //Int64
                    check:=readprocessmemory(processhandle,pointer(realaddress),addr(read6),8,count);
                    if (not check) or (count=0) then result:='??' else
                      begin
                        if memrec[rec].ShowAsHex then
                          result:='0x'+IntToHex(read6,16)
                        else
                          result:=IntToStr(read6);
                      end;
                  end;

    7:            begin  //text
                    if memrec[rec].unicode then
                    begin
                      getmem(read72,memrec[rec].Bit*2+2);
                      check:=readprocessmemory(processhandle,pointer(realaddress),read72,memrec[rec].Bit*2,count);
                      if (not check) or (count<memrec[rec].Bit) then result:='??' else
                      begin
                        read72[memrec[rec].Bit]:=chr(0);
                        result:=read72;
                      end;
                      freemem(read72);
                    end
                    else
                    begin
                      getmem(read7,memrec[rec].Bit+1);
                      check:=readprocessmemory(processhandle,pointer(realaddress),read7,memrec[rec].Bit,count);
                      if (not check) or (count<memrec[rec].Bit) then result:='??' else
                      begin
                        read7[memrec[rec].Bit]:=chr(0);
                        result:=read7;
                      end;
                      freemem(read7);
                    end;
                  end;

    8:            begin //array of byte
                    setlength(read8,memrec[rec].Bit);
                    check:=readprocessmemory(processhandle,pointer(realaddress),read8,memrec[rec].Bit,count);

                    if (not check) or (count<memrec[rec].Bit) then result:='??' else
                    begin
                      temp:='';
                      for j:=0 to memrec[rec].Bit-1 do
                        temp:=temp+IntToHex(read8[j],2)+' ';

                      result:=temp;
                    end;

                    setlength(read8,0);
                  end;

    end;
  end else
  begin
    if memrec[rec].ShowAsHex then
    begin
      if memrec[rec].VarType=0 then result:=IntToHex(memrec[rec].frozenvalue,2) else
      if memrec[rec].VarType=1 then result:=IntToHex(memrec[rec].frozenvalue,4) else
      if memrec[rec].VarType=2 then result:=IntToHex(memrec[rec].frozenvalue,8);
    end
    else
    begin
      if formsettings.cbShowAsSigned.checked then
      begin
        if memrec[rec].VarType=0 then result:=IntToStr(ShortInt(memrec[rec].frozenvalue)) else
        if memrec[rec].VarType=1 then result:=IntToStr(SmallInt(memrec[rec].frozenvalue)) else
        if memrec[rec].VarType=2 then result:=IntToStr(LongInt(memrec[rec].frozenvalue));
      end else
      begin
        if memrec[rec].VarType=0 then result:=IntToStr(byte(memrec[rec].frozenvalue)) else
        if memrec[rec].VarType=1 then result:=IntToStr(word(memrec[rec].frozenvalue)) else
        if memrec[rec].VarType=2 then result:=IntToStr(dword(memrec[rec].frozenvalue));
      end;
    end;



    if memrec[rec].VarType=3 then  //signle
    begin
      read4:=FrozenFvalue[rec];
      result:=FloatToStr(read4);
    end;

    if memrec[rec].VarType=4 then  //double
    begin
      read5:=FrozenFvalue[rec];
      result:=FloatToStr(read5);
    end;

    if memrec[rec].Vartype=5 then //binary
    begin
      //turn arround
      temp2:=frozenstrings[rec];

      temp:='';
      for j:=length(temp2) downto 1 do
        temp:=temp+temp2[j];

      if formsettings.cbBinariesAsDecimal.checked then
        result:=IntToStr(bintoint(temp))
      else
        result:=temp;
    end;

    if memrec[rec].VarType=6 then  //int64
    begin
      if memrec[rec].ShowAsHex then
        result:=IntToHex(memrec[rec].frozenvalue,1)
      else
        result:=IntToStr((memrec[rec].frozenvalue));
    end;

    if memrec[rec].VarType=7 then //text
    begin
      result:=frozenstrings[rec];
    end;

    if memrec[rec].VarType=8 then //array of byte
    begin
      temp:='';
      for j:=0 to length(frozenbytes[rec])-1 do
        temp:=temp+IntToHex(FrozenBytes[rec][j],2)+' ';
      result:=temp;
    end;

  end;

end;

procedure TMainform.reinterpretaddresses;
var i: integer;
    a: dword;
    haserror: boolean;
begin
  //a:=gettickcount;

  try
    if assigned(formscanning) and formscanning.Visible then exit; //dont do it during a scan (slow)
  except

  end;

  //update reinterpetable addresses
  for i:=0 to numberofrecords-1 do
  begin
    if memrec[i].interpretableaddress<>'' then
    begin
      a:=symhandler.getAddressFromName(memrec[i].interpretableaddress,false, haserror); //don't wait for symbols here
      if not haserror then memrec[i].address:=a;
    end;

    if memrec[i].IsPointer and (memrec[i].pointers[length(memrec[i].pointers)-1].interpretableaddress<>'') then
    begin
      a:=symhandler.getAddressFromName(memrec[i].pointers[length(memrec[i].pointers)-1].interpretableaddress,false,haserror);
      if not haserror then
        memrec[i].pointers[length(memrec[i].pointers)-1].Address:=a;
    end;
  end;


  //showmessage(inttostr(gettickcount-a));  //always 0 ticks...
end;

procedure TMainForm.UpdateList;
var i,j,k: Integer;
    rec: Integer;
    count: dword;

    realaddress,realaddress2: dword;
    stopnow: boolean;
    check: boolean;

begin
//

  for i:=0 to (numberoflines-1) do
  begin
    stopnow:=false;

    rec:=scrollbar1.Position+i;
    if (rec)<numberofrecords then
    begin
      if memrec[rec].IsPointer then
      begin
        //find the real address
        realaddress2:=memrec[rec].pointers[length(memrec[rec].pointers)-1].Address;
        for j:=length(memrec[rec].pointers)-1 downto 0 do
        begin
          count:=0;
          check:=readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count);
          if check and (count=4) then
            realaddress2:=realaddress+memrec[rec].pointers[j].offset
          else
          begin
            value[i].Caption:='??';
            address[i].Caption:='P->????????';
            stopnow:=true;
            break;
          end;

        end;
        if stopnow then continue;

        realaddress:=realaddress2;
        address[i].Caption:='P->'+IntToHex(realaddress,8);
      end else realaddress:=memrec[rec].Address;


    //get the value!!!
      if memrec[rec].VarType=255 then
        value[i].Caption:='<script>'
      else
        value[i].Caption:=getStringFromRecord(rec)


    end;
  end;
end;

procedure TMainForm.FreezeThem;
var i,j,k: Integer;
    nrofbytes: integer;
    write: dword;
    write1: byte;
    write2: word;
    write3: dword;
    write4: single;
    write5: double;
    write6: Int64;

    write8: array of byte;
    write9: pbyte;

    writes: pchar;
    error: boolean;

    realaddress,realaddress2: dword;
    count:dword;
    check:boolean;

    originalprotection: dword;
begin
  for i:=0 to numberofrecords-1 do
    if memrec[i].frozen then
    begin
      if memrec[i].IsPointer then
      begin
        //find the real address
        realaddress2:=memrec[i].pointers[length(memrec[i].pointers)-1].Address;
        for j:=length(memrec[i].pointers)-1 downto 0 do
        begin
          check:=readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count);
          if check and (count=4) then
            realaddress2:=realaddress+memrec[i].pointers[j].offset
          else
            continue;
        end;
        realaddress:=realaddress2;
      end else realaddress:=memrec[i].Address;

      error:=false;

      if memrec[i].vartype<255 then //make writable
        VirtualProtectEx(Processhandle,pointer(realaddress),8,PAGE_EXECUTE_READWRITE, originalprotection);

      case memrec[i].VarType of
        0:      begin
                  if memrec[i].Frozendirection=0 then
                  begin
                    write1:=byte(memrec[i].FrozenValue);
                    writeprocessmemory(processhandle,pointer(realaddress),addr(write1),1,write);
                  end
                  else
                  begin
                    readprocessmemory(processhandle,pointer(realaddress),@write1,1,write);
                    if write=1 then
                    if memrec[i].Frozendirection=1 then
                    begin
                      if hotkeypressed=i then
                      begin
                        write1:=write1-memrec[i].FrozenValue; //decrease with frozenvalue
                        writeprocessmemory(processhandle,pointer(realaddress),addr(write1),1,write);
                      end
                      else
                      begin
                        //allow decreased values
                        if write1<=byte(memrec[i].FrozenValue) then memrec[i].FrozenValue:=write1
                        else
                        begin
                          write1:=byte(memrec[i].FrozenValue);
                          writeprocessmemory(processhandle,pointer(realaddress),addr(write1),1,write);
                        end;
                      end
                    end
                    else
                    begin
                      //allow increased values
                      if hotkeypressed=i then
                      begin
                        write1:=write1+memrec[i].FrozenValue; //increase with frozenvalue
                        writeprocessmemory(processhandle,pointer(realaddress),addr(write1),1,write);
                      end
                      else
                      begin
                        if write1>=byte(memrec[i].FrozenValue) then memrec[i].FrozenValue:=write1
                        else
                        begin
                          write1:=byte(memrec[i].FrozenValue);
                          writeprocessmemory(processhandle,pointer(realaddress),addr(write1),1,write);
                        end;
                      end;
                    end;
                  end;
                  error:=write<>1;
                end;

        1:      begin
                  if memrec[i].Frozendirection=0 then
                  begin
                    write2:=word(memrec[i].FrozenValue);
                    writeprocessmemory(processhandle,pointer(realaddress),addr(write2),2,write);
                  end
                  else
                  begin
                    readprocessmemory(processhandle,pointer(realaddress),@write2,2,write);
                    if write=2 then
                    if memrec[i].Frozendirection=1 then
                    begin
                      //allow decreased values
                      if hotkeypressed=i then
                      begin
                        write2:=write2-memrec[i].FrozenValue; //decrease with frozenvalue
                        writeprocessmemory(processhandle,pointer(realaddress),addr(write2),2,write);
                      end
                      else
                      begin
                        if write2<=word(memrec[i].FrozenValue) then memrec[i].FrozenValue:=write2
                        else
                        begin
                          write2:=word(memrec[i].FrozenValue);
                          writeprocessmemory(processhandle,pointer(realaddress),addr(write2),2,write);
                        end;
                      end;
                    end
                    else
                    begin

                      if hotkeypressed=i then
                      begin
                        write2:=write2+memrec[i].FrozenValue;
                        writeprocessmemory(processhandle,pointer(realaddress),addr(write2),2,write);
                      end
                      else
                      begin
                        //allow increased values
                        if write2>=word(memrec[i].FrozenValue) then memrec[i].FrozenValue:=write2
                        else
                        begin
                          write2:=word(memrec[i].FrozenValue);
                          writeprocessmemory(processhandle,pointer(realaddress),addr(write2),2,write);
                        end;
                      end;
                    end;
                  end;
                  error:=write<>2;
                end;

        2:      begin
                  if memrec[i].Frozendirection=0 then
                  begin
                    write3:=memrec[i].FrozenValue;
                    writeprocessmemory(processhandle,pointer(realaddress),addr(write3),4,write);
                  end
                  else
                  begin
                    readprocessmemory(processhandle,pointer(realaddress),@write3,4,write);
                    if write=4 then
                    if memrec[i].Frozendirection=1 then
                    begin
                      if hotkeypressed=i then
                      begin
                        write3:=write3-memrec[i].FrozenValue;
                        writeprocessmemory(processhandle,pointer(realaddress),addr(write3),4,write);
                      end
                      else
                      begin
                        //allow decreased values
                        if write3<=dword(memrec[i].FrozenValue) then memrec[i].FrozenValue:=write3
                        else
                        begin
                          write3:=dword(memrec[i].FrozenValue);
                          writeprocessmemory(processhandle,pointer(realaddress),addr(write3),4,write);
                        end;
                      end;
                    end
                    else
                    begin
                      //allow increased values
                      if hotkeypressed=i then
                      begin
                        write3:=write3+memrec[i].FrozenValue;
                        writeprocessmemory(processhandle,pointer(realaddress),addr(write3),4,write);
                      end
                      else
                      begin

                        if write3>=dword(memrec[i].FrozenValue) then memrec[i].FrozenValue:=write3
                        else
                        begin
                          write3:=dword(memrec[i].FrozenValue);
                          writeprocessmemory(processhandle,pointer(realaddress),addr(write3),4,write);
                        end;
                      end;
                    end;
                  end;
                  error:=write<>4;
                end;

        3:      begin  //float
                  if memrec[i].Frozendirection=0 then
                  begin
                    write4:=FrozenFValue[i];
                    writeprocessmemory(processhandle,pointer(realaddress),addr(write4),4,write);
                  end
                  else
                  begin
                    readprocessmemory(processhandle,pointer(realaddress),@write4,4,write);
                    if write=4 then
                    if memrec[i].Frozendirection=1 then
                    begin
                      if hotkeypressed=i then
                      begin
                        write4:=write4-FrozenFValue[i];
                        writeprocessmemory(processhandle,pointer(realaddress),addr(write4),4,write);
                      end
                      else
                      begin
                        //allow decreased values
                        if write4<=FrozenFValue[i] then FrozenFValue[i]:=write4
                        else
                        begin
                          write4:=FrozenFValue[i];
                          writeprocessmemory(processhandle,pointer(realaddress),addr(write4),4,write);
                        end;
                      end;
                    end
                    else
                    begin
                      if hotkeypressed=i then
                      begin
                        write4:=write4+FrozenFValue[i];
                        writeprocessmemory(processhandle,pointer(realaddress),addr(write4),4,write);
                      end
                      else
                      begin

                        //allow increased values
                        if write4>=FrozenFValue[i] then FrozenFValue[i]:=write4
                        else
                        begin
                          write4:=FrozenFValue[i];
                          writeprocessmemory(processhandle,pointer(realaddress),addr(write4),4,write);
                        end;
                      end;
                    end;
                  end;
                  error:=write<>4;
                end;

        4:      begin //double
                  if memrec[i].Frozendirection=0 then
                  begin
                    write5:=FrozenFValue[i];
                    writeprocessmemory(processhandle,pointer(realaddress),addr(write5),8,write);
                  end
                  else
                  begin
                    readprocessmemory(processhandle,pointer(realaddress),@write5,8,write);
                    if write=8 then
                    if memrec[i].Frozendirection=1 then
                    begin
                      if hotkeypressed=i then
                      begin
                        write5:=write5-FrozenFValue[i];
                        writeprocessmemory(processhandle,pointer(realaddress),addr(write5),8,write);
                      end
                      else
                      begin
                        //allow decreased values
                        if write5<=FrozenFValue[i] then FrozenFValue[i]:=write5
                        else
                        begin
                          write5:=FrozenFValue[i];
                          writeprocessmemory(processhandle,pointer(realaddress),addr(write5),8,write);
                          error:=write<>8;
                        end;
                      end;
                    end
                    else
                    begin
                      //allow increased values
                      if hotkeypressed=i then
                      begin
                        write5:=write5+FrozenFValue[i];
                        writeprocessmemory(processhandle,pointer(realaddress),addr(write5),8,write);
                      end
                      else
                      begin
                        if write5>=FrozenFValue[i] then FrozenFValue[i]:=write5
                        else
                        begin
                          write5:=FrozenFValue[i];
                          writeprocessmemory(processhandle,pointer(realaddress),addr(write5),8,write);
                          error:=write<>8;
                        end;
                      end;
                    end;
                  end;
                  error:=write<>8;
                end;

        5:      begin //bit  (no up or down)
                  nrofbytes:=1+((memrec[i].Bit+memrec[i].bitlength) div 8);
                  setlength(write8,nrofbytes);
                  readprocessmemory(processhandle,pointer(realaddress),addr(write8[0]),nrofbytes,write);

                  j:=memrec[i].Bit;
                  write9:=@write8[0];
                  for k:=1 to memrec[i].bitlength do
                  begin
                    setbit(j,write9^,StrToInt(frozenstrings[i][k]));
                    inc(j);
                    if j>=8 then
                    begin
                      j:=0;
                      inc(write9);
                    end;
                  end;


                  writeprocessmemory(processhandle,pointer(realaddress),addr(write8[0]),nrofbytes,write);
                  error:=write<>nrofbytes;
                end;

        6:      begin  //int64
                  if memrec[i].Frozendirection=0 then
                  begin
                    write6:=memrec[i].FrozenValue;
                    writeprocessmemory(processhandle,pointer(realaddress),addr(write6),8,write);
                  end
                  else
                  begin
                    readprocessmemory(processhandle,pointer(realaddress),@write6,8,write);
                    if write=8 then
                    if memrec[i].Frozendirection=1 then
                    begin
                      if hotkeypressed=i then
                      begin
                        write6:=write6-memrec[i].FrozenValue;
                        writeprocessmemory(processhandle,pointer(realaddress),addr(write6),8,write);
                      end
                      else
                      begin
                        //allow decreased values
                        if write6<=memrec[i].FrozenValue then memrec[i].FrozenValue:=write6
                        else
                        begin
                          write6:=memrec[i].FrozenValue;
                          writeprocessmemory(processhandle,pointer(realaddress),addr(write6),8,write);
                        end;
                      end;
                    end
                    else
                    begin
                      if hotkeypressed=i then
                      begin
                        write6:=write6-memrec[i].FrozenValue;
                        writeprocessmemory(processhandle,pointer(realaddress),addr(write6),8,write);
                      end
                      else
                      begin
                        //allow increased values
                        if write6>=memrec[i].FrozenValue then memrec[i].FrozenValue:=write6
                        else
                        begin
                          write6:=memrec[i].FrozenValue;
                          writeprocessmemory(processhandle,pointer(realaddress),addr(write6),8,write);
                        end;
                      end;
                    end;
                  end;
                  error:=write<>8;
                end;

        7:      begin  //text (no up or down)
                  getmem(writes,memrec[i].Bit+1);

                  StrCopy(writes, PChar(frozenstrings[i]));

                  writeprocessmemory(processhandle,pointer(realaddress),writes,memrec[i].bit,write);

                  freemem(writes);      //if this was heroes 4 v1.0 I would have to remove all freemem statements ;)
                  error:=write<>memrec[i].bit;
                end;

        8:      begin  //array of bytes (no up or down)
                  writeprocessmemory(processhandle,pointer(realaddress),@frozenbytes[i][0],memrec[i].bit,write);
                  error:=write<>memrec[i].bit;
                end;

      end;

      if memrec[i].vartype<255 then //restore
        VirtualProtectEx(Processhandle, pointer(realaddress), 8, originalprotection, originalprotection);

      if error then
      begin
        if not memrec[i].IsPointer then
        begin
          memrec[i].Frozen:=false;
          if (i>=scrollbar1.Position) and (i<=scrollbar1.position+(numberoflines-1)) then updatescreen;
        end; //else keep on freezng as if nothing happened
      end;

    end;
end;

procedure TMainform.AddAutoAssembleScript(script:string);
var error: Integer;
    Address: Dword;
    i,j:  Integer;
    bit: Integer;
    tmp: string;
    pc: ^char;

    found: boolean;
    bitl: integer;

begin
//first check if this address is already in the list!
  inc(NumberOfRecords);
  ReserveMem;

  memrec[NumberOfRecords-1].Description:='Auto assemble cheat';
  memrec[NumberOfRecords-1].Address:=0;
  memrec[NumberOfRecords-1].VarType:=255;

  memrec[NumberOfRecords-1].Frozen:=false;
  memrec[NumberOfRecords-1].FrozenValue:=0;

  memrec[NumberOfRecords-1].Bit:=0;
  memrec[NumberOfRecords-1].bitlength:=0;
  memrec[NumberOfRecords-1].showAsHex:=false;
  memrec[NumberOfRecords-1].autoassemblescript:=script;

  hotkeys[NumberOfRecords-1]:=-1;
  memrec[NumberOfRecords-1].unicode:=false;

  updatescreen;
  updatelist;

  scrollbar1.Position:=scrollbar1.Max-numberoflines+2;
end;

Procedure TMainForm.AddToRecord(line:Integer);
var error: Integer;
    Address: Dword;
    i,j:  Integer;
    bit: Integer;
    tmp: string;
    pc: ^char;

    found: boolean;
    bitl: integer;

    realvartype: integer;
    tempvartype: TVariableType;
begin
//first check if this address is already in the list!

  realvartype:=getvartype;
  if realvartype=5 then //binary
  begin
    bit:=foundlist.getstartbit(line);
    bitl:=foundlist.GetVarLength;
  end
  else
  if realvartype=9 then //all
  begin
    bit:=0;
    bitl:=0;  
    tempvartype:=TVariableType(foundlist.getstartbit(line));
    case tempvartype of
      vtByte: realvartype:=0;
      vtWord: realvartype:=1;
      vtDWord: realvartype:=2;
      vtQWord: realvartype:=6;
      vtSingle: realvartype:=3;
      vtDouble: realvartype:=4;
    end;

  end else
  if realvartype=10 then //custom
  begin
    case scandisplayroutinetype of
      0: realvartype:=0;
      1: realvartype:=1;
      2: realvartype:=2;
      3: realvartype:=6;
      4: realvartype:=3;
      5: realvartype:=4;
      6: realvartype:=8;
      7,8 : realvartype:=7;
      else realvartype:=2;
    end;
  end
  else
  begin
    bit:=0;
    bitl:=0;
    bit:=foundlist.GetVarLength;
  end;
  address:=foundlist.GetAddress(line);

  inc(NumberOfRecords);
  ReserveMem;

  memrec[NumberOfRecords-1].Description:=strNoDescription;
  memrec[NumberOfRecords-1].Address:=address;
  memrec[NumberOfRecords-1].IsPointer:=false;
  setlength(memrec[NumberOfRecords-1].pointers,0);

  if getscantype=string_scan then memrec[NumberOfRecords-1].VarType:=0 else
                                  memrec[NumberOfRecords-1].VarType:=realvartype;

  memrec[NumberOfRecords-1].Frozen:=false;
  memrec[NumberOfRecords-1].FrozenValue:=0;

  memrec[NumberOfRecords-1].Bit:=bit;
  memrec[NumberOfRecords-1].bitlength:=bitl;
  memrec[NumberOfRecords-1].showAsHex:=hexadecimalcheckbox.checked;

  hotkeys[NumberOfRecords-1]:=-1;

  if memrec[NumberOfRecords-1].VarType=7 then //text
  begin
    case scandisplayroutinetype of
      7: memrec[NumberOfRecords-1].unicode:=false;
      8: memrec[NumberOfRecords-1].unicode:=true;
      else memrec[NumberOfRecords-1].unicode:=cbunicode.Checked;
    end;
  end;

  if foundlist.inmodule(line) then
    memrec[NumberOfRecords-1].interpretableaddress:=foundlist.GetModuleNamePlusOffset(line)
  else
    memrec[NumberOfRecords-1].interpretableaddress:='';

  updatescreen;
  updatelist;

  scrollbar1.Position:=scrollbar1.Max-numberoflines+2;
end;

procedure TMainForm.SetExpectedTableName;
var fname: string;
    expectedfilename: string;
begin
  if savedialog1.Filename<>'' then exit;
  if opendialog1.Filename<>'' then exit;

  Fname:=copy(processlabel.caption,pos('-',processlabel.caption)+1,length(processLabel.caption));

  if FName[length(FName)-3]='.' then  //it's a filename
    expectedFilename:=copy(FName,1,length(FName)-4)
  else //it's a normal title;
    expectedFilename:=FName;

  savedialog1.FileName:=expectedFilename;
  Opendialog1.FileName:=expectedFilename;
end;

resourcestring
  strConfirmProcessTermination='This will close the current process. Are you sure you want to do this?';
  strError='Error';
  strErrorwhileOpeningProcess='Error while opening this process';
  strKeepList='Keep the current address list/code list?';
  strInfoAboutTable='Info about this table:';
  strPhysicalMemory='Physical Memory';

function TMainform.openprocessPrologue:boolean;
begin
  result:=false;

  if flashprocessbutton<>nil then
  begin
    flashprocessbutton.Terminate;
    flashprocessbutton:=nil;
  end;


  if (debuggerthread<>nil) and (debuggerthread.attached) then
  begin
    if @DebugActiveProcessStop=@DebugActiveProcessStopProstitute then
    begin
      if messagedlg(strConfirmProcessTermination,mtWarning,[mbYes ,MbNo],0)=mrNo then exit else
      begin
        //whipe out the watchlist
        debuggerthread.debugging:=false;
        terminateprocess(processhandle,0);
      end;
    end;
  end;

  canceled:=false;
  result:=true;
end;

procedure TMainform.openProcessEpilogue(oldprocessname: string; oldprocess: dword; oldprocesshandle: dword;autoattachopen: boolean=false);
var newprocessname: string;
    i,j: integer;
    fname,expectedfilename: string;
    wasActive: boolean; //set to true if the table had AA scripts enabled or the code list had nopped instructions 
begin
  newprocessname:=copy(mainform.ProcessLabel.Caption,pos('-',mainform.ProcessLabel.Caption)+1,length(mainform.ProcessLabel.Caption));

  if (debuggerthread<>nil) and (debuggerthread.attached) then
  begin
    memorybrowser.updateregisterview;
    AdvancedOptions.UpdateAdvancedOptions;
  end;



  symhandler.reinitialize;
  reinterpretaddresses;

  if oldprocess=0 then //set disassembler and hexview of membrowser to what the main header says
    memorybrowser.setcodeanddatabase;

    {
  if resu=mryes then
  begin
    try
      cbfasterscan.Checked:=true;
      foundcount:=0;
      foundlist.Clear;

      newscan.Caption:=strFirstScan;

      Groupbox1.Enabled:=true;
      for i:=0 to groupbox1.ControlCount-1 do
        groupbox1.Controls[i].Enabled:=true;

      scanvalue.Enabled:=true;
      newscan.Enabled:=true;
      nextscanbutton.Enabled:=false;
      vartype.Enabled:=true;
      scantype.Enabled:=true;
      scantext.enabled:=true;
      label4.enabled:=true;
      label8.Enabled:=true;
      HexadecimalCheckbox.Enabled:=true;
      cbCaseSensitive.Enabled:=true;

      scanvalue.visible:=true;
      scantext.Visible:=true;
      scanvalue.text:='';


      Updatescantype;
      Scantype.ItemIndex:=0;

      //-----------------------
      //Get the expectedFilename
      //-----------------------
      SetExpectedTableName;



    except
      processlabel.Caption:=strError;
      raise exception.Create(strErrorWhileOpeningProcess);
    end;

    exit;
  end;
         }



  if (processhandle=0)then
  begin
    if newscan.Caption=strNewScan then newscan.click;

    //disable everything
    foundcount:=0;
    foundlist.Clear;

    newscan.Caption:=strFirstScan;

    Groupbox1.Enabled:=false;
    for i:=0 to groupbox1.ControlCount-1 do
      groupbox1.Controls[i].Enabled:=false;


    scanvalue.Enabled:=false;
    newscan.Enabled:=false;
    nextscanbutton.Enabled:=false;
    vartype.Enabled:=false;
    scantype.Enabled:=false;
    scantext.enabled:=false;
    label4.enabled:=false;
    label8.Enabled:=false;

    scanvalue.visible:=false;
    scantext.Visible:=false;
    scanvalue.text:='';
    HexadecimalCheckbox.Enabled:=false;
    cbCaseSensitive.Enabled:=false;

    Updatescantype;
    Scantype.ItemIndex:=0;

    if cefuncproc.hypermode<>nil then
      freeandnil(cefuncproc.hypermode);

    cbSpeedhack.Enabled:=false;
    cbUnrandomizer.Enabled:=false;



    if processid<>$FFFFFFFF then
    begin
      processlabel.Caption:=strError;
      raise exception.Create(strErrorWhileOpeningProcess);
    end else
    begin
      processlabel.Caption:=strPhysicalMemory;
    end;

    UpdateScanType;
  end;

  if (processID=oldProcess) then exit;



  //a new process has been selected
  cbspeedhack.enabled:=true;
  cbunrandomizer.Enabled:=true;


  if (numberofrecords>0) or (advancedoptions.codelist2.items.Count>0) then
  begin
    if (messagedlg(strKeepList, mtConfirmation, [mbYes, mbNo], 0)=mrNo) then
    begin

      ClearList;
    end
    else
    begin
      //yes, so keep the list
      //go through the list and chek for auto assemble entries, and check if one is enabled. If so, ask to disable (withotu actually disabling)

      wasactive:=false;
      for i:=0 to numberofrecords-1 do
        if (memrec[i].VarType=255) and (memrec[i].Frozen) then
        begin
          wasActive:=true;
          break;
        end;

      if not wasactive then
      begin
        for i:=0 to length(AdvancedOptions.code)-1 do
          if AdvancedOptions.code[i].changed then
          begin
            wasActive:=true;
            break;
          end;
      end;

      if wasactive then
      begin
        if (messagedlg('There are one or more auto assembler entries or code changes enabled in this table. Do you want them disabled? (without executing the disable part)', mtConfirmation, [mbYes, mbNo], 0)=mryes) then
        begin
          for j:=0 to numberofrecords-1 do
            if (memrec[j].VarType=255) and (memrec[j].Frozen) then
              memrec[j].Frozen:=false;

          for j:=0 to length(AdvancedOptions.code)-1 do
            AdvancedOptions.code[i].changed:=false;

          Updatescreen;

          if AdvancedOptions.Visible then
            AdvancedOptions.Codelist2.Repaint;
        end;
        
      end;
    end;

  end;

  enablegui(nextscanbutton.enabled);

  Fname:=copy(processlabel.caption,pos('-',processlabel.caption)+1,length(processLabel.caption));

  if FName[length(FName)-3]='.' then  //it's a filename
    expectedFilename:=copy(FName,1,length(FName)-4)+'.ct'
  else //it's a normal title;
    expectedFilename:=FName+'.ct';


  if not autoattachopen then
  begin
    if fileexists(expectedfilename) or fileexists(cheatenginedir+expectedfilename) then
    begin
      if messagedlg('Load the associated table? ('+expectedFilename+')',mtConfirmation, [mbyes,mbno],0)=mryes then
      begin
        autoopen:=true;
        if fileexists(expectedfilename) then
          opendialog1.FileName:=expectedfilename
        else
          opendialog1.FileName:=cheatenginedir+expectedfilename;

        LoadButton.Click;
      end;
    end;
  end;

  UpdateScanType;
end;

procedure TMainForm.ShowProcessListButtonClick(Sender: TObject);
var oldprocess: Dword;
    resu: integer;
    i,j: integer;
    oldprocesshandle: thandle;
    oldprocessname: string;
    modulelist: tstringlist;
begin
  if not openprocessPrologue then exit;

  oldprocessname:=copy(mainform.ProcessLabel.Caption,pos('-',mainform.ProcessLabel.Caption)+1,length(mainform.ProcessLabel.Caption));
  oldprocess:=processID;
  oldprocesshandle:=processhandle;

  if Processwindow=nil then
    ProcessWindow:=TProcessWindow.Create(nil);
    
  resu:=ProcessWindow.ShowModal;

  if resu=mrCancel then exit;

  openProcessEpilogue(oldprocessname, oldprocess, oldprocesshandle);
end;

procedure TMainform.aprilfoolsscan;
begin
  if aprilfools then
  begin
    if messagedlg('Thank you for trying out Cheat Engine. Because it has expired Cheat Engine will now close. Is that ok with you?',mtInformation,[mbyes,mbno],0)=mryes then
    begin
      showmessage('April fools!!!!');


    end
    else
    begin
      if messagedlg('WHAT!!! Are you saying you''re going to continue using CE ILLEGALLY??? If you say yes, i''m going to mail the cops to get you and send you to jail!!!',mtwarning,[mbyes,mbno],0)=mryes then
        showmessage('Hrmpf... Because I''m in a good mood i''ll let you go this time. But don''t do it again you filthy pirate')
      else
        showmessage('April fools!!!!');
    end;

    caption:=cenorm;
    aprilfools:=false;
  end;
end;

procedure TMainform.donewscan;
var i: integer;
begin
  if SaveFirstScanThread<>nil then //stop saving the results of the fist scan
  begin
    SaveFirstScanThread.Terminate;
    SaveFirstScanThread.WaitFor;
    freeandnil(SaveFirstScanThread);
  end;


  if cbfasterscan.checked then //tell hyperscan it is a new scan
  begin
    if (cefuncproc.hypermode<>nil) and (cefuncproc.hypermode.HyperscanWindow<>0) then
      sendmessage(cefuncproc.hypermode.HyperscanWindow,WM_USER+1,0,0);
  end;

  fastscan:=formsettings.cbFastscan.checked;
  //close files in case of a bug i might have missed...

  vartype.visible:=true;

  foundcount:=0;
  foundlist.Clear;

  newscan.Caption:=strFirstScan;

  nextscanbutton.Enabled:=false;
  vartype.Enabled:=true;

  scanvalue.visible:=true;
  scantext.Visible:=true;

  Updatescantype;
  Scantype.ItemIndex:=0;

  //enable the memory scan groupbox 
  Groupbox1.Enabled:=true;
  for i:=0 to groupbox1.ControlCount-1 do
    groupbox1.Controls[i].Enabled:=true;


  VartypeChange(vartype);
  foundlist.deleteresults;

  if scanvalue.Visible and scanvalue.Enabled then
  begin
    scanvalue.SetFocus;
    scanvalue.SelectAll;
  end
end;


procedure TMainForm.NewScanClick(Sender: TObject);
resourcestring strfillInSomething='Please fill in something!';
               strFirstSelectAProcess='First select a process';

var FromAdd,ToAdd:Dword;
    error: Integer;
//    Tim,Tim2: TTimeStamp;
    Vtype,SType: Integer;
    Processhandle2: Thandle;
    i,j: integer;
    value: string;


    res: word;
    extra: boolean;

    a,b: string;
    winhandle:thandle;
    winprocess: dword;
    roundingtype: tfloatscan;

    value2:string;
    mi: tmoduleinfo;
    fr: dword;

    bytes: tbytes;
begin
  if (not cbfasterscan.checked) then
  begin
    button2.click;
    exit;
  end;
  
  
  if (cefuncproc.hypermode<>nil) and advancedoptions.Pausebutton.down then
    raise exception.Create('Please unpause the game first');

  res:=mrcancel;

  VType:=GetVarType;
  SType:=GetScanType;


  foundlist.Deinitialize;
  
  try
    if scanvalue2<>nil then value2:=scanvalue2.Text;

    screen.Cursor:=crhourglass;

    advanced:=false;
    undoscan.enabled:=false;

    lastscantype:=scantype.ItemIndex;

    case self.roundingtype of
      rtrounded:        roundingtype:=rounded;
      rtExtremerounded: roundingtype:=extremerounded;
      rtTruncated:      roundingtype:=truncated;
    end;

    foundlist.Clear;

    if not nextscanbutton.Enabled then //it's a first scan
    begin
      try
        if (not cbfasterscan.Checked) and (cbPauseWhileScanning.checked) then
        begin
          advancedoptions.Pausebutton.down:=true;
          advancedoptions.Pausebutton.Click;
        end;

      if (scanvalue.visible) and (scanvalue.text='') then raise Exception.Create(strFillInSomething);
      if (scanvalue2<>nil) and (value2='') then raise exception.Create(strFillInSomething);

      if processid<>0 then
      begin
        FromAdd:=ScanStart;
        ToAdd:=ScanStop;


        //--------------------------------------------------

        if (SType=Exact_value) or (SType=String_scan) or (SType=BiggerThan) or (SType=SmallerThan) or (Stype=ValueBetween) then
        begin
          foundcountlabel.visible:=true;

          mainform.caption:=CERegionSearch;
          application.ProcessMessages;
          foundcountlabel.caption:='';

          Processhandle2:=OpenProcess(PROCESS_ALL_ACCESS,false,GetCurrentProcessId);

          try
            if formsettings.checkThread.checked or cbFasterScan.checked then
            begin
              formscanning:=TFormscanning.create(self);
              formscanning.button:=0;
              formscanning.scan:=1;
              formscanning.fromadd:=fromadd;
              formscanning.toadd:=toadd;
              formscanning.readonly:=readonly.checked;
              formscanning.stype:=stype;
              formscanning.vtype:=vtype;
              formscanning.fastscan:=fastscan;
              formscanning.scanvalue:=scanvalue.Text;
              formscanning.scanvalue2:=value2;

              formscanning.hexadecimal:=hexadecimalcheckbox.checked;
              formscanning.unicode:=cbunicode.checked;
              formscanning.LowMemoryUsage:=formsettings.cbLowMemoryUsage.checked;
              formscanning.Skip_PAGE_NOCACHE:=Skip_PAGE_NOCACHE;
              formscanning.ExtremeScan:=cbFasterscan.Checked;
              formscanning.roundingtype:=roundingtype;


              res:=formscanning.showmodal;

            end else
            begin
              foundcount:=0; //obsolete: GetMemoryRangesAndScanValue2(fr,FromAdd,ToAdd,readonly.checked,false,SType,vtype,scanvalue.text,value2,roundingtype,hexadecimalcheckbox.checked,progressbar1,fastscan,cbunicode.checked);
            end;

            if aprilfools then aprilfoolsscan;


            if vtype=5 then
              foundlist3.Columns[0].Width:=90
            else
              foundlist3.Columns[0].Width:=82;

            symhandler.loadmodulelist; //reload this to be sure

            lastwashex:=HexadecimalCheckbox.checked;

          finally

            screen.Cursor:=crdefault;
            progressbar1.Position:=0;
            mainform.Caption:=CEnorm;
            UpdateFoundlisttimer.Enabled:=true;
          end;

          if res=mrcancel then
          begin
            screen.Cursor:=crdefault;
            exit;
          end;

          Groupbox1.Enabled:=false;
          for i:=0 to groupbox1.ControlCount-1 do
            groupbox1.Controls[i].Enabled:=false;

          vartype.Enabled:=false;
          nextscanbutton.enabled:=true;
          newscan.Caption:=strNewScan;
          beep;

          UpdateScanType;

          Scantype.ItemIndex:=lastscantype;
          screen.Cursor:=crdefault;


          if SaveFirstScanThread<>nil then
          begin
            SaveFirstScanThread.Terminate;
            SaveFirstScanThread.WaitFor;
            freeandnil(SaveFirstScanThread);
          end;
          SaveFirstScanThread:=TSaveFirstScanThread.Create(false);

          exit;
        end;

        //---------------------------------------------------------

        mainform.Caption:=CEregion;
        application.ProcessMessages;



        try
          UpdateFoundlisttimer.Enabled:=false;

          if formsettings.checkThread.checked or cbFasterScan.checked then
          begin
            formscanning:=TFormscanning.create(self);
            formscanning.button:=0;
            formscanning.scan:=0;
            formscanning.fromadd:=fromadd;
            formscanning.toadd:=toadd;
            formscanning.readonly:=readonly.checked;
            formscanning.stype:=stype;
            formscanning.vtype:=vtype;
            formscanning.scanvalue:=scanvalue.Text;
            formscanning.scanvalue2:=value2;
            formscanning.fastscan:=fastscan;


            formscanning.LowMemoryUsage:=formsettings.cbLowMemoryUsage.checked;
            formscanning.Skip_PAGE_NOCACHE:=Skip_PAGE_NOCACHE;
            formscanning.ExtremeScan:=cbFasterscan.Checked;
            res:=formscanning.showmodal;


          end else
          foundcount:=0; //obsolete: GetMemoryRanges2(FromAdd,ToAdd,readonly.checked,progressbar1,vtype,fastscan);

          if aprilfools then aprilfoolsscan;
        
        finally
          progressbar1.Position:=0;
          mainform.Caption:=CEnorm;
          UpdateFoundlisttimer.Enabled:=true;

        end;

        if res=mrcancel then
        begin
          screen.Cursor:=crdefault;
          exit;
        end;

        application.ProcessMessages;

        // if Scantype.ItemIndex=String_Scan then foundlabel.caption:=IntToStr(TextSearch(scanvalue.text,foundlist));

        //main datafiles have been generated. Now let Next Scan do the remaining work.
        if not ((Stype=Advanced_scan) or (SType=string_scan)) then NextScanbutton.click else
        begin
          Beep;
        end;

        nextscanbutton.enabled:=true;
        newscan.Caption:=strNewScan;
        vartype.enabled:=false;

        Groupbox1.Enabled:=false;
        for i:=0 to groupbox1.ControlCount-1 do
          groupbox1.Controls[i].Enabled:=false;

        scantype.ItemIndex:=lastscantype;

        //save the results of the fist scan
        if SaveFirstScanThread<>nil then
        begin
          SaveFirstScanThread.Terminate;
          SaveFirstScanThread.WaitFor;
          freeandnil(SaveFirstScanThread);
        end;
        SaveFirstScanThread:=TSaveFirstScanThread.Create(false);


          
      end else showmessage(strFirstSelectaProcess);

      finally
        if (not cbfasterscan.Checked) and (cbPauseWhileScanning.checked) then
        begin
          advancedoptions.Pausebutton.down:=false; //resume
          advancedoptions.Pausebutton.Click;
        end;
      end;



    end else  //it's a new scan
      DoNewScan;

    if stype=string_scan then nextscanbutton.enabled:=false;

    if (foundcount=0) and (SType<>Advanced_scan) then NextScanButton.enabled:=false;

    progressbar1.max:=10;
    progressbar1.Position:=0;
    UpdateScanType;
    UpdateScanType; //second time to force the repaint



    screen.Cursor:=crdefault;


  finally
    scanEpilogue(res=mrcancel);


  end;


end;

procedure TMainForm.NextScanButtonClick(Sender: TObject);
resourcestring strCantdoNextScan='You can''t do a Next Scan with the current selected way of scanning!';
var error: Integer;
    Vtype,SType: Integer;
    hexvalue: string;
    i,j: integer;

    temp,temp2: dword;
    a,b:string;
    FromAdd,ToAdd:Dword;

    roundingtype:tfloatscan;
    value2: string;
    percentage: boolean;

    mi: tmoduleinfo;

    res: word;
    bytes: tbytes;
begin
  if (not cbfasterscan.checked) then
  begin
    button4.click;
    exit;
  end;

  if (cefuncproc.hypermode<>nil) and advancedoptions.Pausebutton.down then
    raise exception.Create('Please unpause the game first');

  if SaveFirstScanThread<>nil then
  begin
    SaveFirstScanThread.WaitFor; //wait till it's done
    freeandnil(SaveFirstScanThread);
  end;

   
  if scanvalue2<>nil then value2:=scanvalue2.Text;
  if cbpercentage<>nil then percentage:=cbpercentage.Checked;


  VType:=GetVarType;
  SType:=GetScanType;

  foundlist.Deinitialize;

  try

    screen.Cursor:=crhourglass;


    if (not cbfasterscan.Checked) and (cbPauseWhileScanning.checked) then
    begin
      advancedoptions.Pausebutton.down:=true;
      advancedoptions.Pausebutton.Click;
    end;

    foundcountlabel.visible:=true;
    VType:=GetVarType;
    SType:=GetScanType;

    if rt1.checked then roundingtype:=rounded;
    if rt2.checked then roundingtype:=extremerounded;
    if rt3.Checked then roundingtype:=truncated;

    mainform.caption:=CESearch;
    application.ProcessMessages;

    try
      UpdateFoundlisttimer.Enabled:=false;

      if not((Stype=Advanced_scan) or (Stype=string_scan)) then
      begin
        if vtype=5 then
        begin
          bitoffsetchange:=0;

          //open the memoryfile end check to see if the length of the bits are what they need to be
          assignfile(Memoryfile,cheatenginedir+'MEMORY.TMP');

          reset(memoryfile,1);
          blockread(memoryfile,temp,4,temp2);
          setlength(bitscan,temp);
          blockread(memoryfile,pointer(bitscan)^,temp,temp2);
          closefile(memoryfile);

          if rbbit.Checked then
            if temp<>length(scanvalue.Text) then
            begin
              formDifferentBitSize:=tformDifferentBitSize.create(self);
              formDifferentBitSize.newbit:=scanvalue.Text;
              formDifferentBitSize.showmodal;
              bitoffsetchange:=formdifferentbitsize.delta;
              formdifferentbitsize.free;
            end;

          if rbdec.checked then
            if temp<>length(inttobin(strtoint(scanvalue.Text))) then
            begin
              formDifferentBitSize:=tformDifferentBitSize.create(self);
              formDifferentBitSize.newbit:=inttobin(strtoint(scanvalue.Text));
              formDifferentBitSize.showmodal;
              bitoffsetchange:=formdifferentbitsize.delta;
              formdifferentbitsize.free;
            end;

          if cbfasterscan.checked then
            hyperscanview.bitoffsetchange:=bitoffsetchange;

        end;


        vartype.Enabled:=false;

        foundlist.Clear;
        foundcountlabel.caption:='';

        if formsettings.checkThread.checked or cbfasterscan.checked then
        begin
          val('$'+FromAddress.text,FromAdd,error);
          val('$'+ToAddress.text,ToAdd,error);

          formscanning:=TFormscanning.create(self);
          formscanning.button:=1;
          formscanning.scan:=2;
          formscanning.stype:=stype;
          formscanning.vtype:=vtype;
          formscanning.fromadd:=fromadd;
          formscanning.toadd:=toadd;
          formscanning.fastscan:=fastscan;
          formscanning.scanvalue:=scanvalue.Text;
          formscanning.scanvalue2:=value2;
          formscanning.hexadecimal:=hexadecimalcheckbox.checked;
          formscanning.unicode:=cbunicode.Checked;
          formscanning.percentage:=percentage;

          formscanning.LowMemoryUsage:=formsettings.cbLowMemoryUsage.checked;
          formscanning.Skip_PAGE_NOCACHE:=Skip_PAGE_NOCACHE;
          formscanning.ExtremeScan:=cbFasterscan.Checked;
          formscanning.roundingtype:=roundingtype;
          res:=formscanning.showmodal;
        end else
        foundcount:=0; //obsolete: nextscan2(scanvalue.text,value2,stype,vtype,roundingtype,hexadecimalcheckbox.Checked,progressbar1,fastscan,cbunicode.checked,percentage);

        foundlist.Clear;

        Beep;



      end else showmessage(strCantDoNextScan);


    finally
      UpdateFoundlisttimer.Enabled:=true;
      mainform.caption:=CENorm;
      progressbar1.max:=10;
      progressbar1.Position:=0;
      screen.Cursor:=crdefault;

      if scanvalue.Enabled then scanvalue.SelectAll;

    end;

  finally
    scanepilogue(res=mrcancel);

    if (not cbfasterscan.Checked) and (cbPauseWhileScanning.checked) then
    begin
      advancedoptions.Pausebutton.down:=false; //resume
      advancedoptions.Pausebutton.Click;
    end;

    UpdateScanType;
  end;
end;

procedure TMainForm.btnMemoryViewClick(Sender: TObject);
begin
  memorybrowser.show;
end;

procedure TMainForm.FormCreate(Sender: TObject);
resourcestring strClickToGoHome='Click here to go to the Cheat Engine homepage';
var pid: dword;
    tokenhandle: thandle;
    tp:TTokenPrivileges;
    prev: TTokenPrivileges;

    ReturnLength: Dword;

    reg: tregistry;
    differentWidth: integer;
    x: array of integer;

    errormode: dword;
begin
  TVistaAltFix.Create(Self);

  errormode:=SetErrorMode(0);
  setErrorMode(errormode or SEM_FAILCRITICALERRORS or SEM_NOOPENFILEERRORBOX);

  foundlist:=tfoundlist.create(foundlist3,foundcountlabel);
  actScriptEngine.ShortCut:=TextToShortCut('Ctrl+Shift+C');


  hotkeypressed:=-1;

  ceclipboardformat:=RegisterClipboardFormat('CE_ENTRY');

  HyperscanFileMapping:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,sizeof(tscansettings),'CEHYPERSCANSETTINGS');
  if HyperscanFileMapping<>0 then
  begin
    HyperscanView:=MapViewOfFile(HyperscanFileMapping,FILE_MAP_ALL_ACCESS,0,0,0);
    if hyperscanview=nil then
      closehandle(HyperscanFileMapping);

    zeromemory(hyperscanview,sizeof(tscansettings));
  end;


  if hyperscanview<>nil then
  begin
    hyperscanview.mainformHandle:=handle;
    hyperscanview.applicantionhandle:=application.Handle;
    hyperscanview.CheatEngineDir:=CheatEngineDir;
    hyperscanview.CEProcessID:=GetCurrentProcessId;
    hyperscanview.CEMainThreadID:=getcurrentthreadid;
  end;



  pid:=GetCurrentProcessID;

  ownprocesshandle:=OpenProcess(PROCESS_ALL_ACCESS,true,pid);
  tokenhandle:=0;

  if ownprocesshandle<>0 then
  begin
    if OpenProcessToken(ownprocesshandle,TOKEN_QUERY or TOKEN_ADJUST_PRIVILEGES	,tokenhandle) then
    begin
      if lookupPrivilegeValue(nil, 'SeDebugPrivilege' ,tp.Privileges[0].Luid) then
      begin
        tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
        tp.PrivilegeCount := 1; // One privilege to set
        if not AdjustTokenPrivileges(tokenhandle,false,tp,sizeof(tp),@prev,returnlength) then
          showmessage('Failure setting the debug privilege. Debugging may be limited.');
      end;
    end;
  end;


  fcontrol:=tfcontrol.Create(self);
  with fcontrol do
  begin
    parent:=panel1;
    OnEnter:=FControlEnter;
    OnExit:=FcontrolExit;
    OnKeyDown:=FControlKeyDown;
    OnKeyPress:=FControlKeyPress;
    PopupMenu:=PopupMenu2;
    helpcontext:=10;
    left:=5;
    top:=57;
    height:=21;
    width:=81;
    taborder:=12;
    sendtoback;

  end;

  tempbitmap:=TBitmap.create;

  scanvalue.text:='';
  windows.OnClick(windows);
  isbit:=false;


  debugger.Semaphore:=createsemaphore(nil,1,1,nil);

  panel3.DoubleBuffered:=true;

  old8087CW:=Get8087CW;
  Set8087CW($133f);


  application.OnException:=exceptionhandler;
  debugproc:=false;

  //get current screen resolution (when switching back for debug)
  originalwidth:=screen.Width;
  originalheight:=screen.Height;

  Memimage:=TMemorystream.Create;
  FirstShiftSelected:=-1;

  oldwidth:=screen.width;
  oldheight:=screen.height;

  oldnumberofrecords:=0;
  ProcessHandler.ProcessHandle:=0;

  logo.Hint:=strClickToGoHome;

  logo.ShowHint:=true;

  numberoflines:=7;
  setlength(frozenbox,7);
  frozenbox[0]:=checkbox1;
  frozenbox[1]:=checkbox2;
  frozenbox[2]:=checkbox3;
  frozenbox[3]:=checkbox4;
  frozenbox[4]:=checkbox5;
  frozenbox[5]:=checkbox6;
  frozenbox[6]:=checkbox7;

  

  setlength(description,7);
  description[0]:=label28;
  description[1]:=label9;
  description[2]:=label17;
  description[3]:=label19;
  description[4]:=label33;
  description[5]:=label32;
  description[6]:=label31;

  setlength(address,7);
  address[0]:=label23;
  address[1]:=label10;
  address[2]:=label20;
  address[3]:=label21;
  address[4]:=label34;
  address[5]:=label35;
  address[6]:=label36;

  setlength(valtype,7);
  valtype[0]:=label18;
  valtype[1]:=label11;
  valtype[2]:=label22;
  valtype[3]:=label24;
  valtype[4]:=label40;
  valtype[5]:=label39;
  valtype[6]:=label37;

  setlength(value,7);
  value[0]:=label13;
  value[1]:=label14;
  value[2]:=label25;
  value[3]:=label26;
  value[4]:=label41;
  value[5]:=label42;
  value[6]:=label43;

  setlength(select,7);
  select[0]:=label12;
  select[1]:=label3;
  select[2]:=label16;
  select[3]:=label15;
  select[4]:=label27;
  select[5]:=label29;
  select[6]:=label30;

  setlength(freezedirection,7);
  freezedirection[0]:=label44;
  freezedirection[1]:=label45;
  freezedirection[2]:=label46;
  freezedirection[3]:=label47;
  freezedirection[4]:=label48;
  freezedirection[5]:=label49;
  freezedirection[6]:=label50;

  updatescreen;

  newaddress:=0;

  VarType.ItemIndex:=3;
  oldvartype:=3;

  UpdateScantype;
  ScanType.ItemIndex:=0;

  newscan.caption:=strFirstScan;
  Updatelist;

  scrollbox1.DoubleBuffered:=true; //remove flickering
  headercontrol1.DoubleBuffered:=true;


  hookedin:=false;

  //allignment fixes for some window style's that mess up with thick borders (like vista)
  differentWidth:=logopanel.left-(clientwidth-logopanel.width);
  button1.Left:=clientwidth-button1.width;
  commentbutton.left:=clientwidth-commentbutton.width;
  logopanel.left:=clientwidth-logopanel.width;
  speedbutton4.Left:=clientwidth-speedbutton4.width;
  progressbar1.Width:=progressbar1.width-differentwidth;
  undoscan.left:=undoscan.left-differentwidth;

  //create object for the auto attach list
  autoattachlist:=tstringlist.create;
  autoattachlist.CaseSensitive:=false; //set it up as not case sensitive

  randomize;

  pluginhandler:=TPluginhandler.create;


{$ifdef ceasinjectabledll}
  //panel7.Visible:=false;
  speedbutton1.enabled:=false;
  processid:=getcurrentprocessid;
  processhandle:=getcurrentprocess;
  enableGui;
  processlabel.Caption:=Inttohex(processid,8)+' : '+'Current process';
{$endif}


  setlength(x,7);
  if loadformposition(self,x) then
  begin
    headercontrol1.Sections[0].Width:=x[0];
    headercontrol1.Sections[1].Width:=x[1];
    headercontrol1.Sections[2].Width:=x[2];
    headercontrol1.Sections[3].Width:=x[3];
    headercontrol1.Sections[4].Width:=x[4];
    panel5.height:=x[5];
    foundlist3.columns[0].width:=x[6];
  end;

  oldhandle:=mainform.handle;
  OnChangedHandle:=ChangedHandle;


  symhandler.loadCommonModuleList;  
end;

procedure TMainForm.ChangedHandle(Sender: TObject);
begin
  memscan.setScanDoneCallback(mainform.handle,wm_scandone);

  //reset the hotkeys
  hotkeyTargetWindowHandleChanged(oldhandle,mainform.handle);
  oldhandle:=mainform.handle;
end;

procedure TMainForm.AddressKeyPress(Sender: TObject; var Key: Char);
begin
  hexadecimal(key);
end;

procedure TMainForm.Panel1DragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
  accept:=(source is TListbox);
end;

procedure TMainForm.Panel1DragDrop(Sender, Source: TObject; X, Y: Integer);
begin
  speedbutton3.click;
end;

procedure TMainForm.FoundListDblClick(Sender: TObject);
begin
  if foundList3.SelCount>0 then
    AddToRecord(FoundList3.ItemIndex);

  FControl.SetFocus;
end;

procedure TMainForm.Browsethismemoryarrea1Click(Sender: TObject);
var a,b: dword;
    s: string;
begin
  if (foundlist3.ItemIndex<>-1) then
  begin
    MemoryBrowser.memoryaddress:=foundlist.GetAddress(foundlist3.itemindex,b,s);
    memorybrowser.show;
  end;
end;

procedure TMainForm.UpdateTimerTimer(Sender: TObject);
begin
  updatetimer.Enabled:=false;

  inc(reinterpretcheck);
  if reinterpretcheck mod 15=0 then reinterpretaddresses;

  UpdateList;
  updatetimer.Enabled:=true;
end;

procedure TMainForm.FreezeTimerTimer(Sender: TObject);
begin

  freezetimer.enabled:=false;
  FreezeThem;
  freezetimer.enabled:=true;
end;

procedure TMainForm.ScrollBar1Change(Sender: TObject);
begin
  updatescreen;
  updatelist;
end;

procedure TMainForm.Label28Click(Sender: TObject);
var newdesc: string;
resourcestring
  strChangeDescription1='Description';
  strChangeDescription2='Change the description to:';
begin
  if lastselected<>scrollbar1.position+(sender as TLabel).tag then exit;

  newdesc:=InputBox(strChangeDescription1,strChangeDescription2,memrec[scrollbar1.position+(sender as TLabel).tag].Description);
  if newdesc='' then newdesc:=strNoDescription;
  memrec[scrollbar1.position+(sender as TLabel).tag].Description:=newdesc;
  updatescreen;
end;

procedure TMainForm.AddressClick(Sender: TObject);
var adr: String;
    newadr: dword;
    error: Integer;
    bit: Byte;
begin

//  if memrec[scrollbar1.position+(sender as TLabel).tag].Frozen then
//    raise Exception.Create('You first have to unfreeze this address before you can change it');

  formaddresschange:=TFormaddresschange.Create(self);
  formaddresschange.index:=scrollbar1.position+(sender as TLabel).tag;
  formaddresschange.index2:=(sender as TLabel).tag;
  formaddresschange.showmodal;
//address popup


  updatescreen;
  updatelist;
end;

procedure TMainForm.TypeClick(Sender: TObject);
var i,j: Integer;
    oldType: Integer;

begin
  OldType:=memrec[scrollbar1.position+(sender as TLabel).tag].VarType;

//  if memrec[scrollbar1.position+(sender as TLabel).tag].Frozen then
//    Raise Exception.Create('You can''t change the type of an frozen value. First unfreeze it!');
  TypeForm.NrOfRecord:=scrollbar1.position+(sender as TLabel).tag;


  If memrec[scrollbar1.position+(sender as TLabel).tag].VarType=0 then TypeForm.VarType.itemindex:=1 else  //byte
  If memrec[scrollbar1.position+(sender as TLabel).tag].VarType=1 then TypeForm.VarType.itemindex:=2 else  //word
  If memrec[scrollbar1.position+(sender as TLabel).tag].VarType=2 then TypeForm.VarType.itemindex:=3 else  //dword
  If memrec[scrollbar1.position+(sender as TLabel).tag].VarType=3 then TypeForm.VarType.itemindex:=5 else  //float
  If memrec[scrollbar1.position+(sender as TLabel).tag].VarType=4 then TypeForm.VarType.itemindex:=6 else  //double
  If memrec[scrollbar1.position+(sender as TLabel).tag].VarType=5 then
  begin
    TypeForm.VarType.itemindex:=0;  //bit
    TypeForm.Edit2.text:=IntToStr(memrec[scrollbar1.position+(sender as TLabel).tag].bitlength);
  end else
  If memrec[scrollbar1.position+(sender as TLabel).tag].VarType=6 then TypeForm.VarType.itemindex:=4 else //int64
  If memrec[scrollbar1.position+(sender as TLabel).tag].VarType=7 then
  begin
    TypeForm.VarType.itemindex:=7;
    typeform.cbunicode.checked:=memrec[scrollbar1.position+(sender as TLabel).tag].unicode;
    TypeForm.Edit1.text:=IntToStr(memrec[scrollbar1.position+(sender as TLabel).tag].bit);
  end else

  if memrec[scrollbar1.position+(sender as TLabel).Tag].VarType=8 then Typeform.VarType.ItemIndex:=8;  


  case memrec[scrollbar1.position+(sender as TLabel).tag].Bit of
  0     :       TypeForm.RadioButton1.checked:=true;
  1     :       TypeForm.RadioButton2.checked:=true;
  2     :       TypeForm.RadioButton3.checked:=true;
  3     :       TypeForm.RadioButton4.checked:=true;
  4     :       TypeForm.RadioButton5.checked:=true;
  5     :       TypeForm.RadioButton6.checked:=true;
  6     :       TypeForm.RadioButton7.checked:=true;
  7     :       TypeForm.RadioButton8.checked:=true;
  end;

  if TypeForm.Showmodal=mrNo then exit;

 
  j:=memrec[scrollbar1.position+(sender as TLabel).tag].VarType;
  for i:=0 to numberofrecords-1 do
  begin
    if (selected[i]) then
    begin
      if memrec[i].vartype<>255 then
        memrec[i].VarType:=j;
      memrec[i].Frozen:=false;
    end;
  end;

  updatescreen;
  updatelist;
end;

//vars for changevalue
var
  differentsizesanswer:boolean;
  terminatewith0answer:boolean;
  askfordifferentsizesonce:boolean;
  asked:boolean;

procedure TMainform.ChangeValue(Itemnr: integer; NewValue:String);
var newvalue1: Byte;
    oldvalue1: byte;
    newvalue2: word;
    newvalue3: dword;
    newvalue4: Single;
    newvalue5: Double;
    newvalue6: Int64;
    newvalueSt: String;
    newvaluest2: widestring;
    newvalue8: TBytes;

    newbytes: array of byte;

    text: pchar;
    addzero: boolean;
    write: dword;
    error,i,j,k,l: Integer;
    bl:integer;

    original: dword;
    thistype: integer;

    nrselected: integer;
    realaddress,realaddress2,count:dword;
    check: boolean;


resourcestring
  strNotTheSameSize1='The text you entered isn''t the same size as the original. Continue?';
  strNotTheSameSize2='Not the same size!';
  strAdd0='Do you want to add a ''0''-terminator at the end?';
  strNotAValidNotation='This is not a valid notation';
  strNotSameAmmountofBytes='The number of bytes you typed is not the same as the previous ammount. Continue?';
  strNotAValidBinaryNotation=' is not a valid binary notation!';
begin
  thistype:=memrec[itemnr].VarType;
  newvaluest:=newvalue;

  error:=0;
  if memrec[itemnr].IsPointer then
  begin
    //find the real address
    realaddress2:=memrec[itemnr].pointers[length(memrec[itemnr].pointers)-1].Address;
    for j:=length(memrec[itemnr].pointers)-1 downto 0 do
    begin
      check:=(realaddress2<($7fffffff-4)) and readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count);
      if check and (count=4) then
        realaddress2:=realaddress+memrec[itemnr].pointers[j].offset
      else
      begin
        beep;
        exit;
      end;


    end;
    realaddress:=realaddress2;
  end else realaddress:=memrec[itemnr].Address;



  case thistype of
    0,1,2,6: begin
                  val(newvaluest,newvalue6,error);
                  if error=0 then
                  begin
                    newvalue1:=byte(newvalue6);
                    newvalue2:=word(newvalue6);
                    newvalue3:=dword(newvalue6);
                  end;
                end;

    3,4:        begin
                  val(newvaluest,newvalue5,error);
                  if error<>0 then
                  begin
                    if newvaluest[error]=',' then newvaluest[error]:='.'
                    else
                    if newvaluest[error]='.' then newvaluest[error]:=',';

                    error:=0;
                    val(newvaluest,newvalue5,error);
                  end;

                  newvalue4:=newvalue5;
                end;

    5:
    begin
      if formsettings.cbBinariesAsDecimal.checked then
      begin
        try
          newvalue6:=StrToInt(newvaluest);
          newvaluest:=inttobin(newvalue6);
        except
          error:=1;
        end;
      end;
    end;

    7:          begin
                  addzero:=false;
                  if length(newvaluest)<>memrec[itemnr].Bit then
                  begin
                    if askfordifferentsizesonce and (not asked) then
                    begin
                      asked:=true;
                      differentsizesanswer:=false;
                      if messagebox(mainform.handle,pchar(strNotTheSameSize1),pchar(strNotTheSameSize2),MB_YESNO or MB_ICONWARNING)=IDNO then exit;
                      differentsizesanswer:=true; //continue
                      //no way back
                      memrec[itemnr].OldValue:=getStringFromRecord(itemnr);
                      addzero:=(messagebox(mainform.handle,pchar(strAdd0),pchar(CEnorm),MB_YESNO or MB_ICONQUESTION) = IDYES);
                      terminatewith0answer:=addzero;
                      memrec[itemnr].Bit:=length(newvaluest);
                    end;

                    if differentsizesanswer then
                    begin
                      //continue
                      addzero:=terminatewith0answer;
                      memrec[itemnr].OldValue:=getStringFromRecord(itemnr);
                      memrec[itemnr].Bit:=length(newvaluest);
                    end;
                  end;

                  newvalue1:=0;
                  newvalue2:=0;

                  if memrec[itemnr].unicode then
                  begin
                    newvaluest2:=newvaluest;


                    VirtualProtectEx(processhandle,  pointer(realaddress),1,PAGE_EXECUTE_READWRITE,original);
                    writeprocessmemory(processhandle,pointer(realaddress),@newvaluest2[1],length(newvaluest2)*2,write);
                    if addzero then writeprocessmemory(processhandle,pointer(realaddress+length(newvaluest)*2),addr(newvalue2),2,write);
                    VirtualProtectEx(processhandle,  pointer(realaddress),1,original,write);

                    frozenstrings[itemnr]:=newvaluest;
                    freemem(text);
                  end
                  else
                  begin
                    getmem(text,length(newvaluest));
                    StrCopy(text, PChar(newvaluest));

                    VirtualProtectEx(processhandle,  pointer(realaddress),1,PAGE_EXECUTE_READWRITE,original);
                    writeprocessmemory(processhandle,pointer(realaddress),text,length(newvaluest),write);
                    if addzero then writeprocessmemory(processhandle,pointer(realaddress+length(newvaluest)),addr(newvalue1),1,write);
                    VirtualProtectEx(processhandle,  pointer(realaddress),1,original,write);

                    frozenstrings[itemnr]:=newvaluest;
                    freemem(text);
                  end;
                  exit;
                end;

    8:          begin
                  for i:=1 to length(newvaluest) do
                  case newvaluest[i] of
                    '0'..'9' : ;
                    'a'..'f' : ;
                    'A'..'F' : ;
                    ' ','-' : ;
                    else raise exception.create(strNotAValidNotation);
                  end;

                  ConvertStringToBytes(newvaluest,true,newvalue8);

                  if length(newvalue8)<>memrec[itemnr].Bit then
                    if messagebox(mainform.handle,pchar(strNotSameAmmountOfBytes),pchar(StrNotTheSameSize2),MB_YESNO or MB_ICONWARNING)=IDNO then exit;

                  memrec[itemnr].OldValue:=getStringFromRecord(itemnr);

                  memrec[itemnr].Bit:=length(newvalue8);
                  setlength(frozenbytes[itemnr],length(newvalue8));

                  for i:=0 to length(newvalue8)-1 do
                    frozenbytes[itemnr][i]:=newvalue8[i];


                  RewriteData(processhandle,realaddress,@frozenbytes[itemnr][0],length(newvalue8));
                  setlength(newvalue8,0);
                  exit;
                end;
  end;


  if error>0 then raise Exception.Create(strNotAValidNotation);

  memrec[itemnr].OldValue:=getStringFromRecord(itemnr);

  i:=itemnr;
  VirtualProtectEx(processhandle,  pointer(realaddress),1,PAGE_EXECUTE_READWRITE,original);

  case memrec[i].VarType of
    0: //byte
    begin
      writeprocessmemory(processhandle,pointer(realaddress),addr(newvalue1),1,write);
      if (hotkeys[i]=-1) or (memrec[i].Frozendirection=0) then memrec[i].FrozenValue:=newvalue1;
    end;

    1: //word
    begin
      writeprocessmemory(processhandle,pointer(realaddress),addr(newvalue2),2,write);
      if (hotkeys[i]=-1) or (memrec[i].Frozendirection=0) then memrec[i].FrozenValue:=newvalue2;
    end;

    2: //dword
    begin
      writeprocessmemory(processhandle,pointer(realaddress),addr(newvalue3),4,write);
      if (hotkeys[i]=-1) or (memrec[i].Frozendirection=0) then memrec[i].FrozenValue:=newvalue3;
    end;

    3: //single
    begin
      writeprocessmemory(processhandle,pointer(realaddress),addr(newvalue4),4,write);
      if (hotkeys[i]=-1) or (memrec[i].Frozendirection=0) then FrozenFValue[i]:=newvalue4
    end;

    4: //double
    begin
      writeprocessmemory(processhandle,pointer(realaddress),addr(newvalue5),8,write);
      if (hotkeys[i]=-1) or (memrec[i].Frozendirection=0) then FrozenFValue[i]:=newvalue5
    end;

    5: //binary
    begin
      bl:=1+((memrec[i].bit+length(newvaluest)-1) div 8);

      setlength(newbytes,bl);
      ReadProcessMemory(processhandle,pointer(realaddress),@newbytes[0],bl,write);

      j:=0;
      k:=memrec[i].bit;
      for l:=length(newvaluest) downto 1 do
      begin
        case newvaluest[l] of
         '0' : setbit(k,newbytes[j],0);
         '1' : setbit(k,newbytes[j],1);
         '*','?': ;
         else raise exception.Create(newvaluest+strNotAValidBinaryNotation);
        end;
        inc(k);
        if k>=8 then
        begin
          inc(j);
          k:=0;
        end;
      end;

      writeprocessmemory(processhandle,pointer(realaddress),@newbytes[0],bl,write);
      frozenstrings[i]:=newvaluest;
      setlength(newbytes,0);
    end;

    6: //Int64
    begin
      writeprocessmemory(processhandle,pointer(realaddress),addr(newvalue6),8,write);
      if (hotkeys[i]=-1) or (memrec[i].Frozendirection=0) then memrec[i].FrozenValue:=newvalue6;
    end;
  end;

  //set old security back
  VirtualProtectEx(processhandle,  pointer(realaddress),1,original,write);
  updatelist;
end;

procedure TMainForm.ValueClick(Sender: TObject);
var newvalue1: Byte;
    oldvalue1: byte;
    newvalue2: word;
    newvalue3: dword;
    newvalue4: Single;
    newvalue5: Double;
    newvalue6: Int64;
    newvalueSt: String;
    newvalue8: TBytes;

    newbytes: array of byte;

    text: pchar;
    addzero: boolean;
    write: dword;
    error,i,j,k,l: Integer;
    bl:integer;

    original: dword;
    thistype: integer;

    nrselected: integer;
    realaddress,realaddress2,count:dword;

    stringsize: integer;


resourcestring strValue='Value';
               strChange1Value='Change this value to:';
               strChangeMoreValues='Change these values to:';

begin
  differentsizesanswer:=false;
  terminatewith0answer:=false;
  askfordifferentsizesonce:=false;
  asked:=false;

  if scrollbar1.position+(sender as TLabel).tag>=NumberOfRecords then exit;

  if memrec[scrollbar1.position+(sender as TLabel).tag].VarType=255 then
  begin
    //auto assembler script
    Changescript1.Click;
    exit;
  end;


  if (value[(sender as TLabel).tag].Caption='??') or (value[(sender as TLabel).tag].Caption='NAN') or (value[(sender as TLabel).tag].Caption='INF') then
  begin
    beep;
    exit;
  end;

  nrselected:=0;
  thistype:=memrec[scrollbar1.position+(sender as TLabel).tag].VarType;
  stringsize:=memrec[scrollbar1.position+(sender as TLabel).tag].Bit;
  askfordifferentsizesonce:=true;

  for i:=0 to numberofrecords-1 do
  begin
    if selected[i] then
    begin
      if stringsize<>memrec[i].Bit then askfordifferentsizesonce:=false;


      inc(nrselected);
      if memrec[i].VarType<>thistype then
      begin
        //check for compatibility
        if ((thistype in [0,1,2,6]) and not (memrec[i].VarType in [0,1,2,6])) or
           ((thistype in [3,4]) and not (memrec[i].VarType in [3,4])) or
           (thistype=5) or
           (thistype=7) or
           (thistype=8) then
        begin
          beep; //stupid lame beepsound
          exit;
        end;
      end;
    end;
  end;



  newvaluest:=value[(sender as TLabel).tag].Caption;

  if thistype in [7,8] then
  begin
    if not InputQuery(strValue,strChange1Value,newvaluest) then exit;
  end
  else
  begin
    if nrselected>1 then
    begin
      if not InputQuery(strValue,strchangeMoreValues,newvaluest) then exit;
    end
    else
    begin
      if not InputQuery(strValue,strChange1Value,newvaluest) then exit;
    end;
  end;


  for i:=0 to numberofrecords-1 do
  begin
    if selected[i] then
      ChangeValue(i,newvaluest);
  end;

  updatelist;
end;

procedure TMainForm.Browsethismemoryregion1Click(Sender: TObject);
var address: dword;
    realaddress,realaddress2: dword;
    j: integer;
    check: boolean;

    count: dword;
begin
  try
    if memrec[lastselected].IsPointer then
    begin
      realaddress2:=memrec[lastselected].pointers[length(memrec[lastselected].pointers)-1].Address;
      for j:=length(memrec[lastselected].pointers)-1 downto 0 do
      begin
        check:=readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count);
        if check and (count=4) then
          realaddress2:=realaddress+memrec[lastselected].pointers[j].offset
        else
          raise exception.Create('The pointer can''t be completly read');
      end;
      address:=realaddress2;

    end
    else
      address:=memrec[lastselected].address;
  except
    address:=memrec[lastselected].address;
  end;
  MemoryBrowser.memoryaddress:=address;

  memorybrowser.show;
end;

procedure TMainForm.Label24ContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
begin
beep;
end;

procedure TMainForm.Deletethisrecord1Click(Sender: TObject);
var i,j: Integer;
    comfirm: Word;
    deletegroup: grouptype;
    IsGroup: boolean;
    multiplegroups: boolean;

resourcestring
  strDelete1Address='Delete this address?';
  strDeleteMultipleAddresses='Delete these addresses?';
  strDelete1Group='Also delete the group this address is a member of?';
  strDeleteMoreGroups='Also delete the groups of the addresses you selected?';
begin
  //delete selectedrecord
  isgroup:=false;
  multiplegroups:=false;
  for i:=1 to 6 do deletegroup[i]:=false;
  i:=0;
  j:=0;

  while (i<numberofrecords) do
  begin
    if selected[i] then
    begin
      inc(j);
      if memrec[i].Group>0 then
      begin
        if isgroup and (deletegroup[memrec[i].Group]) then multiplegroups:=true;
        deletegroup[memrec[i].Group]:=true;
        isgroup:=true;
      end;
    end;

    inc(i);
  end;


  comfirm:=MrNo;
  if j>1 then comfirm:=Messagedlg(strDeleteMultipleAddresses, mtWarning, [mbYes, mbNo], 0);
  if j=1 then comfirm:=Messagedlg(strDelete1Address, mtWarning, [mbYes, mbNo], 0);
  if j=0 then exit;

  if comfirm=mrNo then exit;

  if isgroup and not multiplegroups then comfirm:=Messagedlg(strDelete1group, mtConfirmation, [mbYes, mbNo], 0);
  if isgroup and multiplegroups then comfirm:=Messagedlg(strDeleteMoreGroups, mtConfirmation, [mbYes, mbNo], 0);

  deleterecords;

  if comfirm=mrYes then deletegroups(deletegroup);

end;

procedure TMainForm.SortByFrozenButtonClick(Sender: TObject);
var temprec: memoryrecord;
    tempFvalue: double;
    tempstring: string;
    i,j:       Integer;
    lastfrozen: Integer;
    TempSelected: boolean;
    temphotkey: integer;
    tempbytes: array of byte;
begin
//sort memrec by frozen


  i:=0;
  lastfrozen:=-1;

  while (i<numberofrecords) do
  begin
    if memrec[i].frozen then
    begin
      inc(lastfrozen);
      temprec:=memrec[i];
      memrec[i]:=memrec[lastfrozen];
      memrec[lastfrozen]:=temprec;

      tempfvalue:=FrozenFvalue[i];
      FrozenFvalue[i]:=FrozenFvalue[lastfrozen];
      FrozenFvalue[lastfrozen]:=tempFvalue;

      tempstring:=FrozenStrings[i];
      Frozenstrings[i]:=frozenstrings[lastfrozen];
      frozenstrings[lastfrozen]:=tempstring;

      temphotkey:=hotkeys[i];
      hotkeys[i]:=hotkeys[lastfrozen];
      hotkeys[lastfrozen]:=temphotkey;

      setlength(tempbytes,length(frozenbytes[i]));
      for j:=0 to length(tempbytes)-1 do
        tempbytes[j]:=frozenbytes[i][j];

      setlength(Frozenbytes[i],length(frozenbytes[lastfrozen]));
      for j:=0 to length(Frozenbytes[i])-1 do
        Frozenbytes[i][j]:=FrozenBytes[lastfrozen][j];

      setlength(frozenbytes[lastfrozen],length(tempbytes));
      for j:=0 to length(Tempbytes)-1 do
        Frozenbytes[lastfrozen][j]:=Tempbytes[j];


      if (selected[i]) or (selected[lastfrozen]) then
      begin
        tempselected:=selected[i];
        selected[i]:=selected[lastfrozen];
        selected[lastfrozen]:=tempselected;
      end;

      if (i=lastselected) then LastSelected:=lastfrozen;
      If (lastfrozen=lastselected) then lastselected:=i;
    end;

    inc(i);
  end;

  updatescreen;
  setlength(tempbytes,0);
  FControl.SetFocus;
end;

procedure TMainForm.SortByDescriptionButtonClick(Sender: TObject);
var temprec: memoryrecord;
    i,j:       Integer;
    smallest: Integer;
    tempFvalue: double;
    TempSelected: Boolean;
    tempstring: string;
    temphotkey: integer;
    tempbytes: array of byte;
begin
//sort memrec by frozen

  for i:=0 to numberofrecords-1 do
    begin
      smallest:=i;
      for j:=i to numberofrecords-1 do  //find here the smallest
        if memrec[j].description<memrec[smallest].Description then smallest:=j;
      temprec:=memrec[i];
      memrec[i]:=memrec[smallest];
      memrec[smallest]:=temprec;

      tempfvalue:=FrozenFvalue[i];
      FrozenFvalue[i]:=FrozenFvalue[smallest];
      FrozenFvalue[smallest]:=tempFvalue;

      tempstring:=FrozenStrings[i];
      Frozenstrings[i]:=frozenstrings[smallest];
      frozenstrings[smallest]:=tempstring;

      temphotkey:=hotkeys[i];
      hotkeys[i]:=hotkeys[smallest];
      hotkeys[smallest]:=temphotkey;

      setlength(tempbytes,length(frozenbytes[i]));
      for j:=0 to length(tempbytes)-1 do
        tempbytes[j]:=frozenbytes[i][j];

      setlength(Frozenbytes[i],length(frozenbytes[smallest]));
      for j:=0 to length(Frozenbytes[i])-1 do
        Frozenbytes[i][j]:=FrozenBytes[smallest][j];

      setlength(frozenbytes[smallest],length(tempbytes));
      for j:=0 to length(Tempbytes)-1 do
        Frozenbytes[smallest][j]:=Tempbytes[j];



      if (selected[i]) or (selected[smallest]) then
      begin
        tempselected:=selected[i];
        selected[i]:=selected[smallest];
        selected[smallest]:=tempselected;
      end;

      if (i=lastselected) then LastSelected:=smallest;
      If (smallest=lastselected) then lastselected:=i;

    end;

  updatescreen;
  FControl.SetFocus;
end;

procedure TMainForm.SortByAddressButtonClick(Sender: TObject);
var temprec: memoryrecord;
    i,j:       Integer;
    smallest: Integer;
    TempSelected: boolean;
    TempFvalue: double;
    tempstring: string;
    temphotkey: integer;
    tempbytes: array of byte;
begin
//sort memrec by frozen

  for i:=0 to numberofrecords-1 do
    begin
      smallest:=i;
      for j:=i to numberofrecords-1 do  //find here the smallest
        if memrec[j].address<memrec[smallest].address then smallest:=j;
      temprec:=memrec[i];
      memrec[i]:=memrec[smallest];
      memrec[smallest]:=temprec;

      tempfvalue:=FrozenFvalue[i];
      FrozenFvalue[i]:=FrozenFvalue[smallest];
      FrozenFvalue[smallest]:=tempFvalue;

      tempstring:=FrozenStrings[i];
      Frozenstrings[i]:=frozenstrings[smallest];
      frozenstrings[smallest]:=tempstring;

      temphotkey:=hotkeys[i];
      hotkeys[i]:=hotkeys[smallest];
      hotkeys[smallest]:=temphotkey;

      setlength(tempbytes,length(frozenbytes[i]));
      for j:=0 to length(tempbytes)-1 do
        tempbytes[j]:=frozenbytes[i][j];

      setlength(Frozenbytes[i],length(frozenbytes[smallest]));
      for j:=0 to length(Frozenbytes[i])-1 do
        Frozenbytes[i][j]:=FrozenBytes[smallest][j];

      setlength(frozenbytes[smallest],length(tempbytes));
      for j:=0 to length(Tempbytes)-1 do
        Frozenbytes[smallest][j]:=Tempbytes[j];


      if (selected[i]) or (selected[smallest]) then
      begin
        tempselected:=selected[i];
        selected[i]:=selected[smallest];
        selected[smallest]:=tempselected;
      end;

      if (i=lastselected) then LastSelected:=smallest;
      If (smallest=lastselected) then lastselected:=i;

    end;

  updatescreen;
  FControl.SetFocus;
end;

procedure TMainForm.SortByTypeButtonClick(Sender: TObject);
var temprec: memoryrecord;
    i,j:       Integer;
    smallest: Integer;
    TempFvalue: Double;
    TempSelected: Boolean;
    TempString: string;
    temphotkey: integer;
    tempbytes: array of byte;
begin
//sort memrec by frozen

  for i:=0 to numberofrecords-1 do
    begin
      smallest:=i;
      for j:=i to numberofrecords-1 do  //find here the smallest
        if memrec[j].vartype<memrec[smallest].vartype then smallest:=j;
      temprec:=memrec[i];
      memrec[i]:=memrec[smallest];
      memrec[smallest]:=temprec;

      tempfvalue:=FrozenFvalue[i];
      FrozenFvalue[i]:=FrozenFvalue[smallest];
      FrozenFvalue[smallest]:=tempFvalue;

      tempstring:=FrozenStrings[i];
      Frozenstrings[i]:=frozenstrings[smallest];
      frozenstrings[smallest]:=tempstring;

      temphotkey:=hotkeys[i];
      hotkeys[i]:=hotkeys[smallest];
      hotkeys[smallest]:=temphotkey;

      setlength(tempbytes,length(frozenbytes[i]));
      for j:=0 to length(tempbytes)-1 do
        tempbytes[j]:=frozenbytes[i][j];

      setlength(Frozenbytes[i],length(frozenbytes[smallest]));
      for j:=0 to length(Frozenbytes[i])-1 do
        Frozenbytes[i][j]:=FrozenBytes[smallest][j];

      setlength(frozenbytes[smallest],length(tempbytes));
      for j:=0 to length(Tempbytes)-1 do
        Frozenbytes[smallest][j]:=Tempbytes[j];


      if (selected[i]) or (selected[smallest]) then
      begin
        tempselected:=selected[i];
        selected[i]:=selected[smallest];
        selected[smallest]:=tempselected;
      end;

      if (i=lastselected) then LastSelected:=smallest;
      If (smallest=lastselected) then lastselected:=i;

    end;

  updatescreen;
  FControl.SetFocus;
end;

procedure TMainForm.SortByValueButtonClick(Sender: TObject);
{var temprec: memoryrecord;
    tempammount: int64;
    i,j:       Integer;
    smallest: Integer;
    ammount: array of int64;
    tempammount1: byte;
    tempammount2: word;
    tempammount3: dword;
    tempammount4: int64;
    count: dword;
    TempFvalue: Double;
    TempSelected: Boolean;
    TempString: String;
    TempHotkey: integer;
    TempBytes: array of byte;}
begin
{//sort memrec by frozen
  setlength(ammount,numberofrecords);

  for i:=0 to numberofrecords-1 do
  begin
    if memrec[i].VarType=0 then //byte
    begin
      readprocessmemory(processhandle,pointer(memrec[i].address),addr(tempammount1),1,count);
      if count<1 then ammount[i]:=-1 else ammount[i]:=tempammount1;
    end;

    if memrec[i].VarType=1 then //word
    begin
      readprocessmemory(processhandle,pointer(memrec[i].address),addr(tempammount2),2,count);
      if count<2 then ammount[i]:=-1 else ammount[i]:=tempammount2;
    end;

    if memrec[i].VarType=2 then //dword
    begin
      readprocessmemory(processhandle,pointer(memrec[i].address),addr(tempammount3),4,count);
      if count<4 then ammount[i]:=-1 else ammount[i]:=tempammount3;
    end;

    if (memrec[i].VarType=3) or (memrec[i].vartype=4) then
      ammount[i]:=-1;


    if memrec[i].VarType=6 then //int64
    begin
      readprocessmemory(processhandle,pointer(memrec[i].address),addr(tempammount4),8,count);
      if count<8 then ammount[i]:=-1 else ammount[i]:=tempammount4;
    end;

    if memrec[i].vartype=5 then
    begin
      readprocessmemory(processhandle,pointer(memrec[i].address),addr(tempammount1),1,count);
      if count<1 then ammount[i]:=dword(-1) else
      begin
        case memrec[i].Bit of
          0       :       if (tempammount1 and 1)=0 then ammount[i]:=0 else ammount[i]:=1;
          1       :       if (tempammount1 and 2)=0 then ammount[i]:=0 else ammount[i]:=1;
          2       :       if (tempammount1 and 4)=0 then ammount[i]:=0 else ammount[i]:=1;
          3       :       if (tempammount1 and 8)=0 then ammount[i]:=0 else ammount[i]:=1;
          4       :       if (tempammount1 and 16)=0 then ammount[i]:=0 else ammount[i]:=1;
          5       :       if (tempammount1 and 32)=0 then ammount[i]:=0 else ammount[i]:=1;
          6       :       if (tempammount1 and 64)=0 then ammount[i]:=0 else ammount[i]:=1;
          7       :       if (tempammount1 and 128)=0 then ammount[i]:=0 else ammount[i]:=1;
        end;
      end;
    end;



  end;

  for i:=0 to numberofrecords-1 do
    begin
      smallest:=i;
      for j:=i to numberofrecords-1 do  //find here the smallest
        if ammount[j]<ammount[smallest] then smallest:=j;
      temprec:=memrec[i];
      tempammount:=ammount[i];
      memrec[i]:=memrec[smallest];
      memrec[smallest]:=temprec;
      ammount[smallest]:=tempammount;

      tempfvalue:=FrozenFvalue[i];
      FrozenFvalue[i]:=FrozenFvalue[smallest];
      FrozenFvalue[smallest]:=tempFvalue;

      tempstring:=FrozenStrings[i];
      Frozenstrings[i]:=frozenstrings[smallest];
      frozenstrings[smallest]:=tempstring;

      temphotkey:=hotkeys[i];
      hotkeys[i]:=hotkeys[smallest];
      hotkeys[smallest]:=temphotkey;

      setlength(tempbytes,length(frozenbytes[i]));
      for j:=0 to length(tempbytes)-1 do
        tempbytes[j]:=frozenbytes[i][j];

      setlength(Frozenbytes[i],length(frozenbytes[smallest]));
      for j:=0 to length(Frozenbytes[i])-1 do
        Frozenbytes[i][j]:=FrozenBytes[smallest][j];

      setlength(frozenbytes[smallest],length(tempbytes));
      for j:=0 to length(Tempbytes)-1 do
        Frozenbytes[smallest][j]:=Tempbytes[j];


      if (selected[i]) or (selected[smallest]) then
      begin
        tempselected:=selected[i];
        selected[i]:=selected[smallest];
        selected[smallest]:=tempselected;
      end;

      if (i=lastselected) then LastSelected:=smallest;
      If (smallest=lastselected) then lastselected:=i;

    end;

  updatescreen;
  FControl.SetFocus;}
end;

procedure TMainForm.ScanvalueoldKeyPress(Sender: TObject; var Key: Char);
var correct: boolean;
    becomes: string;
    i,j: integer;
begin
  checkpaste;
  correct:=false;

  if key=chr(13) then
  begin
    if nextscanbutton.Enabled then nextscanbutton.Click else newscan.Click;

    key:=#0;
    exit;
  end;

{  if key=chr(8) then correct:=true else
  if key=chr(16) then correct:=true else
  case vartype.ItemIndex of
  0:   begin  //bit
         if rbbit.checked then
         begin
           if key='0' then correct:=true else
           if key='1' then correct:=true else
           if key='*' then correct:=true else
           if key='?' then correct:=true;
         end else
         begin
           case key of
             '0'..'9' : correct:=true;
           end;
         end;
       end;

  1,2,3,4: begin
           if HexadecimalCheckbox.checked then
             case key of
               '0'..'9' : correct:=true;
               'A'..'F' : correct:=true;
               'a'..'f' : correct:=true;
               '-' : correct:=true;
             end else
             case key of
               '0'..'9' : correct:=true;
               '-' : correct:=true;
             end;
           end;

  5,6,7:   correct:=true; //stupid language settings....

  8:       begin
             becomes:=scanvalue.text;
             if HexadecimalCheckbox.checked then
             begin
               case key of
                 '0'..'9' : correct:=true;
                 'A'..'F' : correct:=true;
                 'a'..'f' : correct:=true;
                 '?','*' : correct:=true;
                 ' ','-'  : correct:=true;  //space and - are the seperators
               end;
             end
             else
             begin
               case key of
                 '0'..'9' : correct:=true;
                 '?','*' : correct:=true;
                 ' ','-'  : correct:=true;
               end;
             end;
           end;

  end;

  if (key='-') and ((scantype.itemindex=1) or (scantype.itemindex=3)) then correct:=false;
  if not correct then key:=chr(0);   }
end;

procedure TMainForm.Calculatenewvaluepart21Click(Sender: TObject);
var newaddress:dword;
    calculate: Integer;
    i,j,err: Integer;
    selectedi: Integer;

    firstispointer,dontdopointers: boolean;
    re: string;
    ok: boolean;

    res: integer;
resourcestring
  strSelectedAddressIsAPointer='The selected address is a pointer. Are you sure? (the base pointer will get the address)';
  strMorePointers='There are more pointers selected. Do you want to change them as well?';
  strMorePointers2='You have selected one or more pointers. Do you want to change them as well?';
  strNotAValidValue='This is not an valid value';
begin
  res:=-1;

  //first find out how many where selected.
  i:=0;
  selectedi:=0;
  while (i<numberofrecords) and (selectedi<2) do
  begin
    if selected[i] then inc(selectedi);
    inc(i);
  end;


  dontdopointers:=false;
  firstispointer:=false;
  if memrec[lastselected].IsPointer then
    if messagedlg(strSelectedAddressIsAPointer,mtConfirmation,[mbyes,mbno],0)<>mryes then exit else firstispointer:=true;

  if selectedi>1 then
  begin
    //see if there are (other) pointers selected
    for i:=0 to numberofrecords-1 do
      if (i<>lastselected) and (selected[i]) and (memrec[i].IsPointer) then
      begin
        if firstispointer then
          re:=strMorePointers
        else
          re:=strMorePointers2;

        if messagedlg(re,mtConfirmation,[mbyes,mbno],0)=mrno then dontdopointers:=true;
        break;
      end;
  end else
  begin
    //all addresses
    for i:=0 to numberofrecords-1 do
      if (i<>lastselected) and (memrec[i].IsPointer) then
      begin
        if firstispointer then
          re:=strMorePointers
        else
          re:=strMorePointers2;

        if messagedlg(re,mtConfirmation,[mbyes,mbno],0)=mrno then dontdopointers:=true;
        break;
      end;
  end;



  newaddress:=memrec[lastselected].address;
  if (foundlist3.SelCount>0) then
    newaddress:=foundlist.GetAddress(foundlist3.ItemIndex);
    

  changeoffset:=TChangeOffset.create(self);

  if memrec[lastselected].IsPointer then
    changeoffset.FromAddress:=memrec[i].pointers[length(memrec[i].pointers)-1].Address
  else
    changeoffset.FromAddress:=memrec[lastselected].address;

  changeoffset.toAddress:=NewAddress;
  if changeoffset.showmodal=mrCancel then exit;

  if changeoffset.error>0 then raise exception.Create(strNotAValidValue);
  calculate:=changeoffset.offset;

  for i:=0 to Numberofrecords-1 do
    if ((selectedi>1) and selected[i]) or (selectedi=1) then
    begin
      if (memrec[i].interpretableaddress<>'') and (not memrec[i].IsPointer) then
      begin
        //check if it's a normal address or a interpretable address
        val('$'+memrec[i].interpretableaddress,j,err);

        if err>0 then
        begin
          if res=-1 then
          begin
            res:=messagedlg('The record with description '''+memrec[i].Description+''' has as interpretable address '''+memrec[i].interpretableaddress+'''. The recalculation will change it to '+symhandler.getNameFromAddress(memrec[i].Address+calculate,true,true)+'. Do you want to edit it to the new address?',mtconfirmation,[mbyes,mbno,mbNoToAll,mbYesToAll,mbCancel],0);
            if res=mrcancel then exit;
          end;

          ok:=(res=mryes) or (res=mrYesToAll);

          if (res=mryes) or (res=mrno) then
            res:=-1; //reset
        end
        else
          ok:=true;


      end else ok:=true;

      if ok then
      begin
        inc(memrec[i].Address,calculate);
        if memrec[i].interpretableaddress<>'' then memrec[i].interpretableaddress:=symhandler.getNameFromAddress(memrec[i].Address,true,true);

        if memrec[i].IsPointer then
        begin
          if not dontdopointers then
          begin
            if memrec[i].pointers[length(memrec[i].pointers)-1].Interpretableaddress<>'' then
            begin
              val('$'+memrec[i].pointers[length(memrec[i].pointers)-1].Interpretableaddress,j,err);
              if err>0 then
              begin
                if res=-1 then
                begin
                  res:=messagedlg('The record with description '''+memrec[i].Description+''' has as interpretable base pointer:'''+memrec[i].pointers[length(memrec[i].pointers)-1].Interpretableaddress+'''. The recalculation will make it '+symhandler.getNameFromAddress((memrec[i].pointers[length(memrec[i].pointers)-1].Address+calculate),true,true)+'. Do you want to edit it to the new address?',mtconfirmation,[mbyes,mbno,mbNoToAll,mbYesToAll,mbCancel],0);
                  if res=mrcancel then exit;
                end;

                ok:=(res=mryes) or (res=mrYesToAll);

                if (res=mryes) or (res=mrno) then
                  res:=-1; //reset
              end
              else
                ok:=true;
            end;

            if ok then
            begin
              inc(memrec[i].pointers[length(memrec[i].pointers)-1].Address,calculate);
              if memrec[i].pointers[length(memrec[i].pointers)-1].Interpretableaddress<>'' then
                memrec[i].pointers[length(memrec[i].pointers)-1].Interpretableaddress:=symhandler.getNameFromAddress(memrec[i].pointers[length(memrec[i].pointers)-1].Address,true,true);
            end;
          end;
        end;
      end;
    end;

  updatescreen;
end;

procedure TMainForm.Button1Click(Sender: TObject);
begin
  if addform=nil then addform:=Taddform.create(self);
  
  addform.showmodal
end;

procedure TMainForm.ScanTypeChange(Sender: TObject);
begin
  updatescantype;

end;

procedure TMainForm.VarTypeChange(Sender: TObject);
var a: int64;
    pa: ^int64;
    pb: ^dword;
    b: double;
    c: Integer;
    d: single;
    i: integer;
    hexvis: boolean;
    decbitvis: boolean;
    hexleft: integer;
    hextext: string;
    hexwidth: integer;
    casevis: boolean;

    oldscantype: integer;
    error: integer;
    temp:string;

    newvartype: integer;
    unicodevis: boolean;
    tc:tbitmap;
begin
  newvartype:=vartype.ItemIndex;

  dontconvert:=true;

  hexvis:=true;
  unicodevis:=false;
  hexleft:=rbbit.Left;
  hexwidth:=50;

  hextext:='Hex';
  casevis:=false;

  decbitvis:=false;

  //convertroutine:

  case oldvartype of
    0:  //it was a bit
    begin
      case newvartype of
        1,2,3,4,5,6:
        begin
          //convert it to a normal value
          if rbbit.checked then
          begin
            //convert it to a decimal value
            rbdec.Checked:=true;
            rbdec.OnClick(rbdec);
          end;
        end;

        7: ; //just leave it

        8:  //array of byte
        begin
          //first convert it to a array of byte
          if rbbit.checked then
          begin
            //convert it to a decimal value
            rbdec.Checked:=true;
            rbdec.OnClick(rbdec);
          end;

          //now convert it to a array of byte
          try
            a:=strtoint(scanvalue.text);
            scanvalue.text:=vartobytes(@a,8);
          except
            scanvalue.text:='';
          end;

        end;
      end;
    end;

    1,2,3,4,5,6,9:
    begin
      //it was one of the normal values
      hexstateForIntTypes:=hexadecimalcheckbox.Checked;

      case newvartype of
        0: //it gets converted to a binary
        begin
          //set

          if oldvartype in [1,2,3,4] then
          begin
            try
              if hexadecimalcheckbox.Checked then
                a:=strtoint('$'+scanvalue.text)
              else
                a:=strtoint(scanvalue.text);
              scanvalue.Text:=inttostr(a);
            except
              scanvalue.text:='';
            end;
          end
          else
          if oldvartype=5 then
          begin
            try
              d:=strtofloat(scanvalue.Text);
              pb:=@d;
              scanvalue.Text:=inttostr(pb^);
            except
              scanvalue.text:='';
            end;
          end else
          if oldvartype=6 then
          begin
            try
              b:=strtofloat(scanvalue.Text);
              pa:=@b;
              scanvalue.Text:=inttostr(pa^);
            except
              scanvalue.text:='';
            end;
          end;

          isbit:=false;
          rbdec.checked:=true;
          rbdec.OnClick(rbdec);
        end;

        1,2,3,4:
        begin
           //converted to a normal type
          if oldvartype in [5,6] then
          begin
            try
              scanvalue.text:=inttostr(trunc(strtofloat(scanvalue.text)));
            except
              scanvalue.Text:='';
            end;

          end;

        end;

        5,6: ; //converted to a float, leave it the same

        7: ;//converted to a string , leave it

        8: //converted to a array of byte
        begin
          if oldvartype in [1,2,3,4] then
          begin
            //now convert it to a array of byte
            if oldvartype in [1,2,3,4] then
            begin
              try
                a:=strtoint(scanvalue.text);
                scanvalue.text:=vartobytes(@a,8);
              except
                scanvalue.text:='';
              end;
            end
            else
            if oldvartype=5 then
            begin
              try
                d:=strtofloat(scanvalue.Text);
                scanvalue.Text:=vartobytes(@d,4);
              except
                scanvalue.text:='';
              end;
            end else
            if oldvartype=6 then
            begin
              try
                b:=strtofloat(scanvalue.Text);
                scanvalue.Text:=vartobytes(@b,8);
              except
                scanvalue.text:='';
              end;
            end;

          end;
        end;


      end;
    end;


    7: //it was text
    begin
      case newvartype of
        0: //it becomes a binary
        begin
          //convert the text to to a decimal value if possible
          try
            a:=strtoint(scanvalue.text);
            scanvalue.Text:=inttostr(a);
          except
            scanvalue.text:='';
          end;
        end;

        1,2,3,4:
        begin
          //convert it to a decimal value
          //allow all characters from '0' to '9' and break if it doesn't
          val(scanvalue.text,a,i);
          scanvalue.Text:=inttostr(a);
        end;

        5,6:
        begin
          //convert the string to a float
          //same as dec, but allow . and , and E and -
          val(scanvalue.text,b,i);
          scanvalue.Text:=format('%.2f',[b]);
        end;

        8:
        begin
          //convert the string to a array of bytes
          temp:='';
          for i:=1 to length(scanvalue.text) do
            temp:=temp+inttohex(ord(scanvalue.Text[i]),2)+' ';

          scanvalue.text:=copy(temp,1,length(temp)-1);


        end;

      end;
    end;


    8: //it was a array of bytes
    begin
      case newvartype of
        0: //it becomes a binary
        begin
          //convert it to a decimal value
          rbdec.checked:=true;
          isbit:=false;
          scanvalue.text:=IntToStr(ByteStringToInt(scanvalue.Text,HexadecimalCheckbox.checked));
        end;

        1,2,3,4: //it becomes a normal decimal value
        begin
          scanvalue.text:=IntToStr(ByteStringToInt(scanvalue.Text,HexadecimalCheckbox.checked));
        end;

        5: //it becomes a float/single
        begin
          scanvalue.Text:=floattostr(bytestringtosingle(scanvalue.text,hexadecimalcheckbox.checked));
        end;

        6: //it becomes a double
        begin
          scanvalue.Text:=floattostr(bytestringtodouble(scanvalue.text,hexadecimalcheckbox.checked));
        end;

        7: //convert it to a string
        begin
          scanvalue.text:=bytestringtotext(scanvalue.text,hexadecimalcheckbox.checked);
        end;

      end;

    end;
  end;

  oldvartype:=vartype.itemindex;

  if not (oldscantype in [smallerthan,biggerthan,valueBetween,exact_value,Advanced_Scan]) then
    scantype.itemindex:=0;

  case newvartype of
  0: begin //binary
       rbdec.checked:=true;
       hexadecimalcheckbox.Checked:=false;
       HexadecimalCheckbox.visible:=false;
       decbitvis:=true;
       Scantype.itemindex:=0;
     end;

   1,2,3,4,9,10:
     begin
       casevis:=false;
       if newvartype in [9,10] then
         hexvis:=false
       else
         hexvis:=true;
         
       scanvalue.MaxLength:=0;
       hexadecimalcheckbox.enabled:=newscan.enabled;
       hexadecimalcheckbox.Checked:=hexstateForIntTypes;
     end;

  5: begin //float;
       casevis:=false;

       hexadecimalcheckbox.Checked:=false;
       HexadecimalCheckbox.enabled:=false;
       scanvalue.MaxLength:=0;
     end;

  6: begin //double
       hexvis:=false;
       temp:=scanvalue.text;


       hexadecimalcheckbox.Checked:=false;
       HexadecimalCheckbox.enabled:=false;
       scanvalue.MaxLength:=0;
     end;

  7: begin //text
       scantype.itemindex:=0;
       casevis:=true;
       cbCasesensitive.Checked:=true;
       cbCasesensitive.ShowHint:=false;
       unicodevis:=true;



       hexadecimalcheckbox.enabled:=newscan.enabled;
       hexadecimalcheckbox.checked:=cbCaseSensitive.checked;
       hexvis:=false;
       hextext:='Unicode';
       hexleft:=170;
       hexwidth:=61;
     end;

  8: begin  //array of byte
       scantype.itemindex:=0;
       scanvalue.MaxLength:=0;
       hexadecimalcheckbox.enableD:=newscan.enabled;
       hexadecimalcheckbox.Checked:=true;
     end;


  end;

  hexadecimalcheckbox.Caption:=hextext;

  tc:=tbitmap.Create;
  tc.canvas.Font:=hexadecimalcheckbox.Font;
  hexwidth:=tc.canvas.TextWidth(hextext)+22;
  tc.free;
  hexadecimalcheckbox.width:=hexwidth;
  hexadecimalcheckbox.left:=scanvalue.Left-hexwidth;
  HexadecimalCheckbox.visible:=hexvis;
  rbdec.visible:=decbitvis;
  rbbit.Visible:=decbitvis;
  cbunicode.Visible:=unicodevis;

  cbCaseSensitive.visible:=casevis;

  cbfastscan.Enabled:=(vartype.ItemIndex in [2..6]) and newscan.enabled;

  UpdateScanType;
  dontconvert:=false;

  //set the old vartype
  oldvartype:=vartype.itemindex;

  for i:=0 to panel5.ControlCount-1 do
  begin
    panel5.Controls[i].Refresh;
    panel5.Controls[i].Repaint;
    panel5.Controls[i].Invalidate;
  end;

end;

procedure TMainForm.LogoClick(Sender: TObject);
begin
  if messagedlg('Do you want to go to the Cheat Engine website?',mtconfirmation,[mbyes,mbno],0)=mryes then
    ShellExecute(0, pchar('open'),pchar('http://www.cheatengine.org/?referedby=CE56'), pchar(''),pchar(''), SW_MAXIMIZE	);

end;

procedure TMainForm.WindowsClick(Sender: TObject);
begin
  FromAddress.text:='00000000';
  ToAddress.text:='7FFFFFFF';
end;

procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose:=CheckIfSaved;
end;

procedure TMainForm.SpeedButton2Click(Sender: TObject);
resourcestring
  strdeleteall='Are you sure you want to delete all addresses?';
var i: integer;
begin
  if editingscript then exit; //don't do it when editing a script

  if numberofrecords>0 then
  begin
    if messagedlg(strdeleteall,mtWarning,[mbYes,mbNo],0)=mrNo then exit;
    numberofRecords:=0;

    for i:=0 to numberofrecords-1 do
    begin
      if hotkeys[i]<>-1 then
        unregisterhotkey(handle,hotkeys[i]);
      hotkeys[i]:=-1;
      hotkeystrings[i]:='';
    end;

    updatelist;
    updatescreen;
  end;

  reservemem;
end;

procedure TMainForm.SpeedButton3Click(Sender: TObject);
resourcestring
  stralreadyin='This address is already in the list';
  stralreadyinlistmultiple='One or more addresses where already in the list';
var i: Integer;
    morein: boolean;
begin
  morein:=false;
  for i:=0 to foundlist3.Items.Count-1 do
    try
      if foundlist3.Items[i].Selected then AddToRecord(i);
    except
      if foundlist3.SelCount=1 then raise exception.Create(stralreadyin) else morein:=true;
    end;

  if morein then showmessage(stralreadyinlistmultiple);
  FControl.SetFocus;
end;

procedure TMainForm.Selectallitems1Click(Sender: TObject);
var i: Integer;
begin
  foundlist3.SelectAll;
end;

procedure TMainForm.Label37Click(Sender: TObject);
begin
beep;
end;

procedure TMainForm.Freezealladdresses2Click(Sender: TObject);
{ scan each item in memrec, if it's not frozen freeze it by getting the current
 value of the address and putting it in the right value type
 Then set frozen to true and update the visible list}
var i,j,k: Integer;
    db: Byte;
    dw: Word;
    dd: Dword;
    a: Single;
    b: double;
    dI64: int64;
    temps: pchar;

    multiple,check: Boolean;
    error: dword;
    controle:string;

    temp: string;
    read8: array of byte;
    read9: pbyte;

    realaddress,realaddress2,count:dword;

begin

  if memrec[lastselected].vartype=255 then
  begin
    enableautoassemblecheat(lastselected);
    updatelist;
    updatescreen;
    exit;
  end;

  j:=0;
  i:=0;
  while (j<2) and (i<numberofrecords) do
  begin
    if selected[i] then inc(j);
    inc(i);
  end;

  multiple:=(j>1);

  for i:=0 to numberofrecords-1 do
  begin

    if not memrec[i].Frozen then
    begin
      if memrec[i].IsPointer then
      begin
        //find the real address
        realaddress2:=memrec[i].pointers[length(memrec[i].pointers)-1].Address;
        for j:=length(memrec[i].pointers)-1 downto 0 do
        begin
          check:=readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count);
          if check and (count=4) then
            realaddress2:=realaddress+memrec[i].pointers[j].offset;
        end;
        realaddress:=realaddress2;
      end else realaddress:=memrec[i].Address;


      memrec[i].Frozendirection:=0;
      //
      if (not multiple) or (multiple and selected[i]) then
        case memrec[i].VarType of
              0       :       begin  //byte
                                readprocessmemory(processhandle,pointer(realaddress),addr(db),1,error);
                                if error=1 then
                                begin
                                  memrec[i].FrozenValue:=db;
                                  memrec[i].Frozen:=true;
                                end;
                              end;

              1       :      begin  //word
                               readprocessmemory(processhandle,pointer(realaddress),addr(dw),2,error);
                               if error=2 then
                               begin
                                 memrec[i].FrozenValue:=dw;
                                 memrec[i].Frozen:=true;
                               end;
                             end;

              2       :      begin  //dword
                               readprocessmemory(processhandle,pointer(realaddress),addr(dd),4,error);
                               if error=4 then
                               begin
                                 memrec[i].FrozenValue:=dd;
                                 memrec[i].Frozen:=true;
                               end;
                             end;

              3       :      begin
                               readprocessmemory(processhandle,pointer(realaddress),addr(a),4,error);
                               if error=4 then
                               begin
                                 controle:=FloatToStr(a);
                                 if system.pos('NAT',controle)>0 then exit;
                                 if system.pos('INF',controle)>0 then exit;
                                 frozenfvalue[i]:=a;
                                 memrec[i].Frozen:=true;
                               end;
                             end;

              4       :      begin
                               readprocessmemory(processhandle,pointer(realaddress),addr(b),8,error);
                               if error=8 then
                               begin
                                 controle:=FloatToStr(b);
                                 if system.pos('NAT',controle)>0 then exit;
                                 if system.pos('INF',controle)>0 then exit;
                                 frozenfvalue[i]:=b;
                                 memrec[i].Frozen:=true;
                               end;
                             end;

              5       :      begin  //bit
                               k:=1+((memrec[i].Bit+memrec[i].bitlength) div 8);
                               setlength(read8,k);

                               readprocessmemory(processhandle,pointer(realaddress),addr(read8[0]),k,error);
                               if error=k then
                               begin
                                 //find out the current bit combination (use frozenstrings to store the value)

                                 //convert what i need to a string of bits
                                 temp:='';
                                 j:=memrec[i].Bit;
                                 read9:=@read8[0];
                                 for k:=1 to memrec[i].bitlength do
                                 begin
                                   temp:=temp+IntToStr(getbit(j,read9^));
                                   inc(j);
                                   if j>=8 then
                                   begin
                                     j:=0;
                                     inc(read9);
                                   end;
                                 end;

                                 //the tempstring now contaisn the bits (bit0 is first char...)
                                 frozenstrings[i]:=temp;
                                 memrec[i].Frozen:=true;
                               end;
                             end;

              6       :      begin  //int64
                               readprocessmemory(processhandle,pointer(realaddress),addr(dI64),8,error);
                               if error=8 then
                               begin
                                 memrec[i].FrozenValue:=di64;
                                 memrec[i].Frozen:=true;
                               end;
                             end;

              7       :      begin  //text
                               getmem(temps,memrec[i].bit+1);
                               readprocessmemory(processhandle,pointer(realaddress),temps,memrec[i].Bit,error);
                               if error=memrec[i].bit then
                               begin
                                 temps[memrec[i].bit]:=#0;
                                 FrozenStrings[i]:=temps;
                                 memrec[i].Frozen:=true;
                               end;
                               freemem(temps);
                             end;

              8       :      begin  //array of byte
                               setlength(FrozenBytes[i],memrec[i].bit);
                               readprocessmemory(processhandle,pointer(realaddress),FrozenBytes[i],memrec[i].Bit,error);
                               if error=memrec[i].bit then
                                 memrec[i].Frozen:=true;
                              end;

              {255     :      begin
                               enableautoassemblecheat(i);

                             end; }



        end;

    end;
  end;

  updatelist;
  updatescreen;
end;


procedure TMainForm.SlectItem(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var sel: Integer;
    i: Integer;
begin
  FControl.SetFocus;

//only react to one click
 // if sender=Label38 then exit;


  sel:=0;
  if sender is TLabel then
  begin


    sel:=(Sender as TLabel).Tag+scrollbar1.Position;
    if sel>numberofrecords-1 then
    begin
      if not ((ssSHift in Shift) or (ssCtrl in Shift) or (ssRight in Shift)) then
      begin
        for i:=0 to numberofrecords-1 do
        begin
          selected[i]:=false;
        end;
        updatescreen;
      end;

      exit;
    end;
  end;

  if sender is TCheckBox then
    sel:=(Sender as TCheckBox).Tag+scrollbar1.Position;


  if not ((ssShift) in (Shift)) then FirstShiftSelected:=-1;


  if ssLeft in Shift then
  begin
    if not (ssShift in Shift) and not (ssCtrl in Shift) then
    begin
      for i:=0 to numberofrecords-1 do
        selected[i]:=false;
    end;

    if (sel>=numberofrecords) then
    begin
      updatelist;
      updatescreen;
      exit;
    end;

    if ssShift in shift then
    begin

      if FirstShiftSelected=-1 then FirstShiftSelected:=lastselected;

      //select everything from FirstShiftSelected to sel
      for i:=0 to numberofrecords-1 do selected[i]:=false;

      if FirstShiftSelected<sel then
        for i:=FirstShiftselected to sel do selected[i]:=true
      else
        for i:=FirstShiftSelected downto sel do selected[i]:=true;

      lastselected:=sel;

      updatelist;
      updatescreen;
      exit;
    end;


    if ssCtrl in shift then
    begin
      selected[sel]:=not selected[sel];
      if selected[sel] then lastselected:=sel;
      updatelist;
      updatescreen;
      exit;
    end;


    selected[sel]:=true;

  end;

  if ssRight in shift then
  begin
    if (sel>=numberofrecords) then
    begin
      updatelist;
      updatescreen;
      exit;
    end;

    if not selected[sel] then //clear all other selected items except this one
    begin
      for i:=0 to numberofrecords-1 do selected[i]:=false;
    end;

    selected[sel]:=true;

  end;

  lastselected:=sel;

  updatelist;
  Updatescreen;
end;

procedure TMainForm.PopupMenu2Popup(Sender: TObject);
resourcestring
  strsethotkey='Set a hotkey';
  strshowasdecimal='Show as decimal value';
  strshowashex='Show as hexadecimal value';
  strFreezeAddressInList='Freeze the address in this list';
  strFreezeAllAddresses='Freeze all addresses in this list';
  strUnfreezeAllAddresses='Unfreeze all addresses in this list';
  strUnfreezeAddressInList='Unfreeze the address in this list';
  strDeleteAddress='Delete this address';
  strDeleteTheseAddresses='Delete these addresses';
  strRecalculateAddress='Recalculate address';
  strRecalculateSelectedAddresses='Recalculate selected addresses';
  strRecalculateAllAddresses='Recalculate all addresses';

  strRemoveFromGroup='Remove from group ';

  strChangeScript='Change script';
  strEnableCheat='Enable cheat';
  strDisableCheat='Disable cheat';

  strForceRecheck='Force recheck symbols';

var i: Integer;
    selectedi: Integer;
    number: Integer;
    clip: TClipboard;
    inclipboard: boolean;
    temp: pchar;
    s: string;
begin

  sethotkey1.Caption:=strsethotkey;

  number:=0;
  i:=0;
  selectedi:=0;
  while (selectedi<2) and (i<numberofrecords) do
  begin
    if selected[i] then inc(selectedi);
    inc(i);
  end;
    
  if (lastselected<>-1) and (lastselected<numberofrecords) then
  begin
    if hotkeys[lastselected]<>-1 then sethotkey1.Caption:='Remove the hotkey (currently:'+hotkeystrings[lastselected]+')';

    if memrec[lastselected].VarType in [0,1,2,6] then
      Showashexadecimal1.Visible:=true;

    if memrec[lastselected].ShowAsHex then
      Showashexadecimal1.Caption:=strshowasdecimal
    else
      Showashexadecimal1.Caption:=strshowashex;

    change1.Visible:=(memrec[lastselected].VarType<>255) and (selectedi>0);

  end else
  begin
    Showashexadecimal1.Visible:=false;
    change1.Visible:=false;
  end;

  inclipboard:=false;
  s:=clipboard.AsText;
  if length(s)>1 then
    if s[1]='<' then inclipboard:=true;




  Forcerechecksymbols1.visible:=numberofrecords>0;

  Pointerscanforthisaddress1.Visible:=(numberofrecords>0) and (selectedi>=1);





  if (numberofrecords=0) then //it's a empty list
  begin
    DeleteThisRecord1.visible:=false;
    BrowseThisMemoryRegion1.visible:=false;
    ShowAsHexadecimal1.Visible:=false;
    SetHotkey1.Visible:=false;
    FreezeallAddresses2.visible:=false;
    UnfreezeAllAddresses1.visible:=false;

    n5.visible:=false;
    Setbreakpoint1.visible:=false;
    Findoutwhataccessesthisaddress1.Visible:=false;

    sep1.Visible:=false;
    CalculateNewValuePart21.visible:=false;
    n4.visible:=false;
    cut1.Enabled:=false;
    copy1.Enabled:=false;
    paste1.Enabled:=inclipboard;

    groupoption1.Visible:=false;
  end;

  if (selectedi=0) and (numberofrecords=1) then //nothing selected, but there is 1 address
  begin
    DeleteThisRecord1.Visible:=false;
    Browsethismemoryregion1.visible:=false;
    ShowAsHexadecimal1.Visible:=false;
    SetHotkey1.Visible:=false;
    FreezeAllAddresses2.Caption:=strfreezeaddressinlist;
    UnfreezeAllAddresses1.Caption:=strunfreezeaddressinlist;
    if memrec[0].Frozen then
    begin
      UnfreezeAllAddresses1.visible:=true;
      FreezeAllAddresses2.visible:=false;
    end
    else
    begin
      UnfreezeAllAddresses1.visible:=false;
      FreezeAllAddresses2.visible:=true;
    end;
    n5.visible:=false;
    Setbreakpoint1.visible:=false;
    Findoutwhataccessesthisaddress1.Visible:=false;

    sep1.Visible:=false;
    CalculateNewValuePart21.Visible:=false;
    n4.Visible:=true;

    cut1.Enabled:=false;
    copy1.Enabled:=false;
    paste1.enabled:=inclipboard;

    N1.Visible:=false;
    groupoption1.visible:=false;
  end;

  if (selectedi=1) and (numberofrecords=1) then //1 selected and 1 record
  begin
    DeleteThisRecord1.Visible:=true;
    DeleteThisRecord1.Caption:=strdeleteaddress;
    Browsethismemoryregion1.Visible:=true;
    ShowAsHexadecimal1.Visible:=true;
    SetHotkey1.Visible:=true;
    FreezeAllAddresses2.Caption:=strfreezeaddressinlist;
    UnfreezeAllAddresses1.Caption:=strunfreezeaddressinlist;
    if memrec[0].Frozen then
    begin
      UnfreezeAllAddresses1.visible:=true;
      FreezeAllAddresses2.visible:=false;
    end
    else
    begin
      UnfreezeAllAddresses1.visible:=false;
      FreezeAllAddresses2.visible:=true;
    end;

    n5.visible:=formsettings.cbShowAdvanced.Checked;
    Setbreakpoint1.visible:=formsettings.cbShowAdvanced.Checked;
//    Findoutwhatreadsfromthisaddress1.visible:=formsettings.cbShowAdvanced.Checked;
    Findoutwhataccessesthisaddress1.Visible:=formsettings.cbShowAdvanced.Checked;


    sep1.Visible:=true;
    CalculateNewValuePart21.Caption:=strRecalculateAddress;
    CalculateNewValuePart21.Visible:=true;
//    CalculateNewValuePart21.Enabled:=(foundlist2.ItemIndex<>-1);
    N4.visible:=true;
    cut1.enabled:=true;
    copy1.enabled:=true;
    paste1.Enabled:=true;
    n1.visible:=true;
    groupoption1.visible:=true;

    Settonogroup1.Caption:=strRemoveFromGroup+IntToStr(memrec[lastselected].Group);
  end;


  if (selectedi=0) and (numberofrecords>1) then //nothing selected but there are more records
  begin
    DeleteThisRecord1.Visible:=false;
    Browsethismemoryregion1.Visible:=false;
    SetHotkey1.Visible:=false;
    FreezeAllAddresses2.Caption:=strFreezeAllAddresses;
    UnfreezeAllAddresses1.Caption:=strUnfreezeAllAddresses;

    for i:=0 to numberofrecords-1 do
      if memrec[i].Frozen then inc(number);

    if number=0 then  //there is no frozen value so unfreeze is impossible
    begin
      UnfreezeAllAddresses1.visible:=false;
      FreezeAllAddresses2.visible:=true;
    end;

    if number=numberofrecords then //all addresses have been frozen
    begin
      UnfreezeAllAddresses1.visible:=true;
      FreezeAllAddresses2.visible:=false;
    end;

    if (number>0) and (number<numberofrecords) then
    begin
      UnfreezeAllAddresses1.visible:=true;
      freezeallAddresses2.visible:=true;
    end;

    n5.Visible:=false;
    Setbreakpoint1.Visible:=false;
    Findoutwhataccessesthisaddress1.Visible:=false;

    sep1.Visible:=true;
    CalculateNewValuePart21.Visible:=false;
    n4.visible:=false;
    cut1.Enabled:=false;
    copy1.enabled:=false;
    paste1.enabled:=inclipboard;
    N1.enabled:=false;
    groupoption1.enabled:=false;


  end;

  if (selectedi=1) and (numberofrecords>1) then
  begin
    DeleteThisRecord1.Visible:=true;
    DeleteThisRecord1.Caption:=strDeleteAddress;
    Browsethismemoryregion1.Visible:=true;
    ShowAsHexadecimal1.Visible:=true;

    SetHotkey1.Visible:=true;
    FreezeAllAddresses2.Caption:=strfreezealladdresses;
    unFreezeallAddresses1.Caption:=strUnfreezeAllAddresses;

    for i:=0 to numberofrecords-1 do
      if memrec[i].Frozen then inc(number);

    if number=0 then  //there is no frozen value so unfreeze is impossible
    begin
      UnfreezeAllAddresses1.visible:=false;
      FreezeAllAddresses2.visible:=true;
    end;

    if number=numberofrecords then //all addresses have been frozen
    begin
      UnfreezeAllAddresses1.visible:=true;
      FreezeAllAddresses2.visible:=false;
    end;

    if (number>0) and (number<numberofrecords) then
    begin
      UnfreezeAllAddresses1.visible:=true;
      freezeallAddresses2.visible:=true;
    end;

    n5.visible:=formsettings.cbShowAdvanced.Checked;
    Setbreakpoint1.visible:=formsettings.cbShowAdvanced.Checked;
//    Findoutwhatreadsfromthisaddress1.visible:=formsettings.cbShowAdvanced.Checked;
    Findoutwhataccessesthisaddress1.Visible:=formsettings.cbShowAdvanced.Checked;

    sep1.Visible:=true;
    CalculateNewValuePart21.Caption:=strRecalculateAllAddresses;
    CalculateNewValuePart21.Visible:=true;
//    CalculateNewValuePart21.Enabled:=(foundlist2.ItemIndex<>-1);

    n4.visible:=true;
    cut1.enabled:=true;
    copy1.Enabled:=true;
    paste1.Enabled:=inclipboard;
    N1.visible:=true;
    groupoption1.visible:=true;
    Settonogroup1.Caption:=strremovefromgroup+IntToStr(memrec[lastselected].Group);
  end;


  if (selectedi>1) and (numberofrecords>1) then
  begin
    DeleteThisRecord1.Visible:=true;
    DeleteThisRecord1.Enabled:=true;
    DeleteThisRecord1.Caption:=strdeleteaddress;
    Browsethismemoryregion1.Visible:=true;
    ShowAsHexadecimal1.Visible:=true;

    SetHotkey1.Visible:=true;
    FreezeAllAddresses2.Caption:=strfreezealladdresses;
    Unfreezealladdresses1.Caption:=strunfreezealladdresses;
    for i:=0 to numberofrecords-1 do
      if memrec[i].Frozen then inc(number);

    if number=0 then  //there is no frozen value so unfreeze is impossible
    begin
      UnfreezeAllAddresses1.visible:=false;
      FreezeAllAddresses2.visible:=true;
    end;

    if number=numberofrecords then //all addresses have been frozen
    begin
      UnfreezeAllAddresses1.visible:=true;
      FreezeAllAddresses2.visible:=false;
    end;

    if (number>0) and (number<numberofrecords) then
    begin
      UnfreezeAllAddresses1.visible:=true;
      freezeallAddresses2.visible:=true;
    end;

    n5.visible:=formsettings.cbShowAdvanced.Checked;
    Setbreakpoint1.visible:=formsettings.cbShowAdvanced.Checked;
//    Findoutwhatreadsfromthisaddress1.visible:=formsettings.cbShowAdvanced.Checked;
    Findoutwhataccessesthisaddress1.Visible:=formsettings.cbShowAdvanced.Checked;


    sep1.Visible:=true;
    calculatenewvaluepart21.Caption:=strrecalculateselectedaddresses;
    CalculateNewValuePart21.Visible:=true;
//    CalculateNewValuePart21.Enabled:=(foundlist2.ItemIndex<>-1);
    N4.Visible:=true;
    cut1.enabled:=true;
    copy1.enabled:=true;
    paste1.enabled:=inclipboard;
    N1.visible:=true;
    groupoption1.visible:=true;
    Setbreakpoint1.Visible:=true;

    Settonogroup1.Caption:=strRemoveFromGroup;
  end;

  address1.enabled:=selectedi=1;
  ype1.Enabled:=selectedi>0;

  if (lastselected<>-1) and (numberofrecords>0) and (memrec[lastselected].VarType=255) then
  begin
    Browsethismemoryregion1.visible:=false;
    Showashexadecimal1.Visible:=false;
    SetHotkey1.Visible:=true;
    sethotkey1.Enabled:=true;
    changescript1.Visible:=true;

    UnfreezeAllAddresses1.caption:=strdisablecheat;
    FreezeAllAddresses2.caption:=strenablecheat;

    n5.visible:=false;
    Findoutwhataccessesthisaddress1.visible:=false;
    Setbreakpoint1.visible:=false;
    sep1.visible:=false;
    Calculatenewvaluepart21.visible:=false;
    N4.visible:=true;
    n1.Visible:=false;
  end else changescript1.Visible:=false;

end;

procedure TMainForm.CheckBox2MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var error: dword;

    a: single;
    b: double;
    controle: String;

    i,j,k,sel: Integer;
    db: Byte;
    dw: Word;
    dd: dword;
    di64: Int64;

    read8: array of byte;
    read9: pbyte;

    freeze,check: boolean;
    freezegroup: array [1..6] of boolean;
    temps: pchar;

    temp: string;
    realaddress,realaddress2,count: dword;
begin

  FControl.SetFocus;

  for i:=1 to 6 do
    freezegroup[i]:=false;

  if ssRight in Shift then
  begin
    if not selected[(sender as TCheckBox).Tag+scrollbar1.Position] then //clear all other selected items except this one
    begin
      for i:=0 to numberofrecords-1 do
        selected[i]:=false;
    end;
  end;

  if not((ssShift in Shift) or (ssCtrl in Shift)) then
  begin
    for i:=0 to numberofrecords-1 do
      selected[i]:=false;
  end;

  if not ((ssShift) in (Shift)) then FirstShiftSelected:=-1;

  sel:=(sender as TCheckBox).Tag+scrollbar1.Position;

  if ssShift in shift then
  begin
    if FirstShiftSelected=-1 then FirstShiftSelected:=lastselected;

    //select everything from FirstShiftSelected to sel
    for i:=0 to numberofrecords-1 do selected[i]:=false;

    if FirstShiftSelected<sel then
      for i:=FirstShiftselected to sel do selected[i]:=true
    else
      for i:=FirstShiftSelected downto sel do selected[i]:=true;

    lastselected:=sel;
  end;



  selected[(sender as TCheckBox).Tag+scrollbar1.Position]:=true;
  lastselected:=(sender as TCheckBox).Tag+scrollbar1.Position;

  freeze:=not frozenbox[(sender as TCheckbox).Tag].checked;

  //find groups to be frozen/unfrozen
  for i:=0 to numberofrecords-1 do
  begin
    if (memrec[i].Group>0) and (selected[i]) then
      freezegroup[memrec[i].Group]:=true;  //freezegroup can also be used to unfreeze
  end;

  for i:=0 to numberofrecords-1 do
  begin

    if freeze then //freeze all selected items
    begin
      if memrec[i].IsPointer then
      begin
        //find the real address
        realaddress2:=memrec[i].pointers[length(memrec[i].pointers)-1].Address;
        for j:=length(memrec[i].pointers)-1 downto 0 do
        begin
          check:=readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count);
          if check and (count=4) then
            realaddress2:=realaddress+memrec[i].pointers[j].offset;
        end;
        realaddress:=realaddress2;
      end else realaddress:=memrec[i].Address;


      if (selected[i] and not memrec[i].Frozen) or
         ((memrec[i].group>0) and freezegroup[(memrec[i].Group)])
      then //if it's selected and not yet frozen freeze it.
      begin
        //freeze that address
        memrec[i].Frozendirection:=0;
        case memrec[i].VarType of
              0       :       begin  //byte
                                readprocessmemory(processhandle,pointer(realaddress),addr(db),1,error);
                                if error=1 then
                                begin
                                  memrec[i].FrozenValue:=db;
                                  memrec[i].Frozen:=true;
                                end;
                              end;

              1       :      begin  //word
                               readprocessmemory(processhandle,pointer(realaddress),addr(dw),2,error);
                               if error=2 then
                               begin
                                 memrec[i].FrozenValue:=dw;
                                 memrec[i].Frozen:=true;
                               end;
                             end;

              2       :      begin  //dword
                               readprocessmemory(processhandle,pointer(realaddress),addr(dd),4,error);
                               if error=4 then
                               begin
                                 memrec[i].FrozenValue:=dd;
                                 memrec[i].Frozen:=true;
                               end;
                             end;

              3       :      begin
                               readprocessmemory(processhandle,pointer(realaddress),addr(a),4,error);
                               if error=4 then
                               begin
                                 controle:=FloatToStr(a);
                                 if system.pos('NAT',controle)>0 then exit;
                                 if system.pos('INF',controle)>0 then exit;
                                 frozenfvalue[i]:=a;
                                 memrec[i].Frozen:=true;
                               end;
                             end;

              4       :      begin
                               readprocessmemory(processhandle,pointer(realaddress),addr(b),8,error);
                               if error=8 then
                               begin
                                 controle:=FloatToStr(b);
                                 if system.pos('NAT',controle)>0 then exit;
                                 if system.pos('INF',controle)>0 then exit;
                                 frozenfvalue[i]:=b;
                                 memrec[i].Frozen:=true;
                               end;
                             end;

              5       :      begin  //binary
                               k:=1+((memrec[i].Bit+memrec[i].bitlength) div 8);
                               setlength(read8,k);

                               readprocessmemory(processhandle,pointer(realaddress),addr(read8[0]),k,error);
                               if error=k then
                               begin
                                 //find out the current bit combination (use frozenstrings to store the value)

                                 //convert what i need to a string of bits
                                 temp:='';
                                 j:=memrec[i].Bit;
                                 read9:=@read8[0];
                                 for k:=1 to memrec[i].bitlength do
                                 begin
                                   temp:=temp+IntToStr(getbit(j,read9^));
                                   inc(j);
                                   if j>=8 then
                                   begin
                                     j:=0;
                                     inc(read9);
                                   end;
                                 end;

                                 //the tempstring now contaisn the bits (bit0 is first char...)
                                 frozenstrings[i]:=temp;
                                 memrec[i].Frozen:=true;
                               end;
                             end;

              6       :      begin  //int64
                               readprocessmemory(processhandle,pointer(realaddress),addr(dI64),8,error);
                               if error=8 then
                               begin
                                 memrec[i].FrozenValue:=di64;
                                 memrec[i].Frozen:=true;
                               end;
                             end;

              7       :      begin  //text
                               getmem(temps,memrec[i].bit+1);
                               readprocessmemory(processhandle,pointer(realaddress),temps,memrec[i].Bit,error);
                               if error=memrec[i].bit then
                               begin
                                 temps[memrec[i].bit]:=#0;
                                 FrozenStrings[i]:=temps;
                                 memrec[i].Frozen:=true;
                               end;
                               freemem(temps);
                             end;

              8       :      begin  //array of byte
                               setlength(FrozenBytes[i],memrec[i].bit);
                               readprocessmemory(processhandle,pointer(realaddress),FrozenBytes[i],memrec[i].Bit,error);
                               if error=memrec[i].bit then
                                 memrec[i].Frozen:=true;
                             end;

              255     :      enableautoassemblecheat(i); //auto assemble script

        end;
      end;
    end
    else
    begin
      {freeze is false, so UNFREEZE all selected items and groups}
      if selected[i] then
      begin
        if memrec[i].VarType=255 then
          disableautoassemblecheat(i)
        else
          memrec[i].frozen:=false;
      end;

      if (memrec[i].group>0) and (freezegroup[memrec[i].group]) then
      begin
        if memrec[i].VarType=255 then
          disableautoassemblecheat(i)
        else
          memrec[i].frozen:=false;
      end;
    end;
  end;

  sethotkey1.Enabled:=memrec[lastselected].VarType<>255;

  UpdateScreen;
end;

procedure TMainForm.CheckBox1Click(Sender: TObject);
begin
  UpdateScreen;
end;

procedure TMainForm.Unfreezealladdresses1Click(Sender: TObject);
var i: Integer;
begin
  if memrec[lastselected].vartype=255 then
  begin
    disableautoassemblecheat(lastselected);
    exit;
  end;           

  for i:=0 to numberofrecords-1 do
  begin
    if memrec[i].VarType=255 then
      disableautoassemblecheat(i)
    else
      memrec[i].Frozen:=false;
  end;

  updatelist;
  updatescreen;
end;

procedure TMainForm.PopupMenu1Popup(Sender: TObject);
begin
  Browsethismemoryregioninthedisassembler1.Enabled:=Foundlist3.SelCount>=1;

  if foundlist3.Items.Count=0 then
  begin
    Removeselectedaddresses1.enabled:=false;
    Browsethismemoryarrea1.enabled:=false;
    Selectallitems1.enabled:=false;
  end else
  begin
    Removeselectedaddresses1.enabled:=true;
    Browsethismemoryarrea1.enabled:=True;

    Selectallitems1.enabled:=foundlist3.Items.Count<5000;
  end;

  if Foundlist3.SelCount>1 then
    Removeselectedaddresses1.caption:='Remove selected addresses'
  else
    Removeselectedaddresses1.caption:='Remove selected address';

  if Foundlist3.selcount=0 then
  begin
    Removeselectedaddresses1.enabled:=false;
    Browsethismemoryarrea1.enabled:=false;
  end else
  begin
    Removeselectedaddresses1.enabled:=true;
    Browsethismemoryarrea1.enabled:=true;
  end;

  Removeselectedaddresses1.Visible:=not (GetVarType in [5,8]);

end;

procedure TMainForm.Removeselectedaddresses1Click(Sender: TObject);
var address: Dword;
    e,i,j: Integer;
    bit: Byte;
    selected: array of integer;
begin
  if SaveFirstScanThread<>nil then
  begin
    SaveFirstScanThread.WaitFor; //wait till it's done
    freeandnil(SaveFirstScanThread);
  end;

  if foundlist3.selcount=1 then //use itemindex (faster)
  begin
		foundlist.deleteaddress(foundlist3.itemindex);
	end
	else if foundlist3.selcount>1 then
	begin
    if foundlist3.items.count>100000 then
      if messagedlg('This list is huge and deleting multiple items will require CE to traverse the whole list and can take a while. Are you sure?',mtconfirmation,[mbyes,mbno],0)<>mryes then exit;

    screen.Cursor:=crhourglass;

   	MainForm.Caption:=CEWait;
    Mainform.Refresh;

    foundlist3.Items.BeginUpdate;
    try
      j:=0;
      setlength(selected, foundlist3.selcount);
      for i:=0 to foundlist3.items.count-1 do
      begin
        if foundlist3.items[i].Selected then
        begin
          selected[j]:=i;
          inc(j);
        end;
      end;

      for i:=length(selected)-1 downto 0 do
        foundlist.deleteaddress(selected[i]);

		finally
	    Mainform.caption:=CENorm;
   		screen.Cursor:=crDefault;
      foundlist3.Items.EndUpdate;
		end;
	end;

	foundlist.deinitialize;
	foundlist.initialize(getvartype);
end;


procedure TMainForm.FControlKeyPress(Sender: TObject; var Key: Char);
begin
  key:=chr(0);

end;

procedure TMainForm.FControlKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var i,j,k: Integer;
    comfirm: Dword;
    doit,check: Boolean;
    freeze: Boolean;
    db: Byte;
    dw: Word;
    dd: dword;
    di64: Int64;
    a: single;
    b: double;
    error: Dword;
    temps: pchar;

    read8: array of byte;
    read9: pbyte;
    temp: string;

    controle: String;

    select: Integer;
    realaddress,realaddress2,count:dword;

procedure FreezeOrUnfreezeSelected;
var i,j,k: integer;
begin
  if lastselected>=numberofrecords then exit;

   freeze:=not memrec[lastselected].frozen;

   for i:=0 to numberofrecords-1 do
   begin
     if memrec[i].ispointer then
     begin
       //find the real address
       realaddress2:=memrec[i].pointers[length(memrec[i].pointers)-1].address;
       for j:=length(memrec[i].pointers)-1 downto 0 do
       begin
         check:=readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count);
         if check and (count=4) then
           realaddress2:=realaddress+memrec[i].pointers[j].offset;
       end;
       realaddress:=realaddress2;
     end else realaddress:=memrec[i].address;

     if (hotkeys[i]=-1) and (selected[i]) then
     begin
         if not freeze then
         begin
           if memrec[i].VarType=255 then
             disableautoassemblecheat(i)
           else
             memrec[i].frozen:=false;
         end
         else
         begin  //freeze
           memrec[i].frozendirection:=0;

           case memrec[i].vartype of
             0       :       begin  //byte
                               readprocessmemory(processhandle,pointer(realaddress),addr(db),1,error);
                               if error=1 then
                               begin
                                 memrec[i].frozenvalue:=db;
                                 memrec[i].frozen:=true;
                               end;
                             end;

              1       :      begin  //word
                               readprocessmemory(processhandle,pointer(realaddress),addr(dw),2,error);
                               if error=2 then
                               begin
                                 memrec[i].frozenvalue:=dw;
                                 memrec[i].frozen:=true;
                               end;
                             end;

              2       :      begin  //dword
                               readprocessmemory(processhandle,pointer(realaddress),addr(dd),4,error);
                               if error=4 then
                               begin
                                 memrec[i].frozenvalue:=dd;
                                 memrec[i].frozen:=true;
                               end;
                             end;

              3       :      begin
                               readprocessmemory(processhandle,pointer(realaddress),addr(a),4,error);
                               if error=4 then
                               begin
                                 controle:=floattostr(a);
                                 if system.pos('nat',controle)>0 then exit;
                                 if system.pos('inf',controle)>0 then exit;
                                 frozenfvalue[i]:=a;
                                 memrec[i].frozen:=true;
                               end;
                             end;

              4       :      begin
                               readprocessmemory(processhandle,pointer(realaddress),addr(b),8,error);
                               if error=8 then
                               begin
                                 controle:=floattostr(a);
                                 if system.pos('nat',controle)>0 then exit;
                                 if system.pos('inf',controle)>0 then exit;
                                 frozenfvalue[i]:=b;
                                 memrec[i].frozen:=true;
                               end;
                             end;

             5       :      begin  //bit
                              k:=1+((memrec[i].bit+memrec[i].bitlength) div 8);
                              setlength(read8,k);

                              readprocessmemory(processhandle,pointer(realaddress),addr(read8[0]),k,error);
                              if error=k then
                              begin
                                //find out the current bit combination (use frozenstrings to store the value)

                                //convert what i need to a string of bits
                                temp:='';
                                j:=memrec[i].bit;
                                read9:=@read8[0];
                                for k:=1 to memrec[i].bitlength do
                                begin
                                  temp:=temp+inttostr(getbit(j,read9^));
                                  inc(j);
                                  if j>=8 then
                                  begin
                                    j:=0;
                                    inc(read9);
                                  end;
                                end;

                                //the tempstring now contaisn the bits (bit0 is first char...)
                                frozenstrings[i]:=temp;
                                memrec[i].frozen:=true;
                              end;
                            end;

             6       :      begin  //int64
                              readprocessmemory(processhandle,pointer(realaddress),addr(di64),8,error);
                              if error=8 then
                              begin
                                memrec[i].frozenvalue:=di64;
                                memrec[i].frozen:=true;
                              end;
                            end;

             7       :      begin  //text
                              getmem(temps,memrec[i].bit+1);
                              readprocessmemory(processhandle,pointer(realaddress),temps,memrec[i].bit,error);
                              if error=memrec[i].bit then
                              begin
                                temps[memrec[i].Bit]:=#0;
                                frozenstrings[i]:=temps;
                                memrec[i].frozen:=true;
                              end;
                              freemem(temps);
                            end;

             8       :      begin  //text
                              setlength(frozenbytes[i],memrec[i].bit);
                              readprocessmemory(processhandle,pointer(realaddress),frozenbytes[i],memrec[i].bit,error);
                              if error=memrec[i].bit then
                                memrec[i].frozen:=true;
                            end;

             255      :     begin
                              enableautoassemblecheat(i);
                            end;

           end;


         end;

     end;
   end;

   updatescreen;
   updatelist;

end;

var tempmemrec: memoryrecord;
    tempfvalue: double;
    tempstring: string;
    TempSelected: boolean;
    temphotkey: integer;
    tempbytes: array of byte;
        
    sel1,sel2: integer;
    nrselected: integer;
begin
  if ((key=ord('S')) and (ssctrl in shift)) then
  begin
    if editingscript then exit;

    //swap
    nrselected:=0;
    for i:=0 to NumberOfRecords-1 do
    begin
      if selected[i] then
      begin
        inc(nrselected);
        if nrselected=1 then sel1:=i;
        if nrselected=2 then sel2:=i;
        if nrselected=3 then
        begin
          beep;
          exit;
        end;
      end;

    end;
    if nrselected<>2 then
    begin
      beep;
      exit;
    end;

    tempmemrec:=memrec[sel1];
    memrec[sel1]:=memrec[sel2];
    memrec[sel2]:=tempmemrec;

    tempfvalue:=FrozenFvalue[sel2];
    FrozenFvalue[sel2]:=FrozenFvalue[sel1];
    FrozenFvalue[sel1]:=tempFvalue;

    tempstring:=FrozenStrings[sel2];
    Frozenstrings[sel2]:=frozenstrings[sel1];
    frozenstrings[sel1]:=tempstring;

    temphotkey:=hotkeys[sel2];
    hotkeys[sel2]:=hotkeys[sel1];
    hotkeys[sel1]:=temphotkey;

    setlength(tempbytes,length(frozenbytes[sel2]));
    for j:=0 to length(tempbytes)-1 do
      tempbytes[j]:=frozenbytes[sel2][j];

    setlength(Frozenbytes[sel2],length(frozenbytes[sel1]));
    for j:=0 to length(Frozenbytes[sel2])-1 do
      Frozenbytes[sel2][j]:=FrozenBytes[sel1][j];

    setlength(frozenbytes[sel1],length(tempbytes));
    for j:=0 to length(Tempbytes)-1 do
      Frozenbytes[sel1][j]:=Tempbytes[j];



    updatescreen;
    updatelist;
    exit;
  end;

  if ((key=ord('E')) and (ssCtrl in Shift) and not (ssAlt in Shift)) then
  begin
    edit;
    exit;
  end;

  if ((key=ord('C')) and (ssCtrl in Shift) and not (ssAlt in Shift)) then
  begin
    copyselectedrecords;
    exit;
  end;

  if ((key=ord('V')) and (ssCtrl in Shift) and not (ssAlt in Shift)) then
  begin
    Paste(formsettings.cbsimplecopypaste.checked);
    exit;
  end;

  if ((key=ord('X')) and (ssCtrl in Shift) and not (ssAlt in Shift)) then
  begin
    copyselectedrecords;
    deleterecords;
    exit;
  end;

  if ((key=ord('Z')) and (ssCtrl in Shift) and not (ssAlt in Shift)) then
  begin
    //toggle the selected items
    for i:=0 to numberofrecords-1 do
      if selected[i] and (memrec[i].OldValue<>'') then
        ChangeValue(i,memrec[i].OldValue);
    exit;
  end;

  if ((key=ord('A')) and (ssctrl in Shift) and not (ssalt in Shift)) then
  begin
    //select all
    for i:=0 to numberofrecords-1 do
      selected[i]:=true;

    updatescreen;
  end;


  case key of
    ord('A')..ord('Z'),ord('0')..ord('9'): begin
                          if not (ssCtrl in Shift) then
                          begin

                            select:=-1;
                            for i:=lastselected+1 to numberofrecords-1 do
                            begin
                              if (length(memrec[i].description[1])>0) and (uppercase(memrec[i].description[1])=uppercase(chr(key))) then
                              begin
                                select:=i;
                                break;
                              end;
                            end;

                            if select=-1 then exit;

                            if not ((ssShift) in (Shift)) then FirstShiftSelected:=-1;

                            if ssShift in Shift then  //ctrl does nothing
                            begin
                              if lastselected<numberofRecords-1 then
                              begin
                                if FirstShiftSelected=-1 then FirstShiftSelected:=lastselected;

                                //select everything from FirstShiftSelected to sel
                                for i:=0 to numberofrecords-1 do selected[i]:=false;

                                Lastselected:=select;

                                if FirstShiftSelected<lastselected then
                                  for i:=FirstShiftselected to lastselected do selected[i]:=true
                                else
                                  for i:=FirstShiftSelected downto lastselected do selected[i]:=true;
                              end;
                            end
                            else
                            begin
                              if lastselected<numberofRecords-1 then
                              begin
                                for i:=0 to numberofRecords-1 do selected[i]:=false;
                                Lastselected:=select;
                                selected[LastSelected]:=true;
                              end;
                            end;

                            if lastselected<scrollbar1.position then scrollbar1.Position:=lastselected;
                            if lastselected>scrollbar1.position+(numberoflines-1) then scrollbar1.Position:=lastselected-(numberoflines-1);

                           Updatescreen;
                          end;
                        end;

    VK_RETURN:begin
                if (lastselected>=0) and (lastselected<NumberOfRecords) then
                begin
                  if ssCtrl in shift then
                    description[lastselected-scrollbar1.position].OnDblClick(value[lastselected-scrollbar1.position])
                  else if ssAlt in shift then
                    address[lastselected-scrollbar1.position].OnDblClick(value[lastselected-scrollbar1.position])
                  else
                    value[lastselected-scrollbar1.position].OnDblClick(value[lastselected-scrollbar1.position]);
                end;
              end;

    VK_HOME:  begin
                if not ((ssShift) in (Shift)) then FirstShiftSelected:=-1;

                if ssShift in Shift then  //ctrl does nothing
                begin
                  if lastselected>0 then
                  begin
                    if FirstShiftSelected=-1 then FirstShiftSelected:=lastselected;

                    //select everything from FirstShiftSelected to sel
                    for i:=0 to numberofrecords-1 do selected[i]:=false;

                    Lastselected:=0;


                    if FirstShiftSelected<lastselected then
                      for i:=FirstShiftselected to lastselected do selected[i]:=true
                    else
                      for i:=FirstShiftSelected downto lastselected do selected[i]:=true;

                  end;

                  scrollbar1.position:=0;
                end
                else
                begin
                  if lastselected>0 then
                  begin
                    for i:=0 to numberofRecords-1 do selected[i]:=false;
                    Lastselected:=0;
                    selected[lastselected]:=true;
                    scrollbar1.Position:=0;
                  end;
                end;
                Updatescreen;
              end;

    VK_END:   begin
                 //
                if not ((ssShift) in (Shift)) then FirstShiftSelected:=-1;

                if ssShift in Shift then  //ctrl does nothing
                begin
                  if lastselected<numberofRecords-1 then
                  begin
                    if FirstShiftSelected=-1 then FirstShiftSelected:=lastselected;

                    //select everything from FirstShiftSelected to sel
                    for i:=0 to numberofrecords-1 do selected[i]:=false;

                    Lastselected:=numberofrecords-1;

                    if FirstShiftSelected<lastselected then
                      for i:=FirstShiftselected to lastselected do selected[i]:=true
                    else
                      for i:=FirstShiftSelected downto lastselected do selected[i]:=true;
                  end;
                end
                else
                begin
                  if lastselected<numberofRecords-1 then
                  begin
                    for i:=0 to numberofRecords-1 do selected[i]:=false;
                    Lastselected:=numberofrecords-1;
                    selected[LastSelected]:=true;
                  end;
                end;

                if lastselected<scrollbar1.position then scrollbar1.Position:=lastselected;
                if lastselected>scrollbar1.position+(numberoflines-1) then scrollbar1.Position:=lastselected-(numberoflines-1);

                Updatescreen;
              end;

    VK_UP:    begin
                if not ((ssShift) in (Shift)) then FirstShiftSelected:=-1;

                if ssShift in Shift then  //ctrl does nothing
                begin
                  if lastselected>0 then
                  begin
                    if FirstShiftSelected=-1 then FirstShiftSelected:=lastselected;

                    //select everything from FirstShiftSelected to sel
                    for i:=0 to numberofrecords-1 do selected[i]:=false;

                    Lastselected:=lastselected-1;


                    if FirstShiftSelected<lastselected then
                      for i:=FirstShiftselected to lastselected do selected[i]:=true
                    else
                      for i:=FirstShiftSelected downto lastselected do selected[i]:=true;

                  end;
                end
                else
                begin
                  if lastselected>0 then
                  begin
                    for i:=0 to numberofRecords-1 do selected[i]:=false;
                    Lastselected:=lastselected-1;
                    selected[lastselected]:=true;
                  end;
                end;

                if lastselected>scrollbar1.position+(numberoflines-1) then scrollbar1.Position:=lastselected-(numberoflines-1);
                if lastselected<scrollbar1.position then scrollbar1.Position:=lastselected;
                Updatescreen;

              end;

    VK_DOWN:  begin
                if not ((ssShift) in (Shift)) then FirstShiftSelected:=-1;

                if ssShift in Shift then  //ctrl does nothing
                begin
                  if lastselected<numberofRecords-1 then
                  begin
                    if FirstShiftSelected=-1 then FirstShiftSelected:=lastselected;

                    //select everything from FirstShiftSelected to sel
                    for i:=0 to numberofrecords-1 do selected[i]:=false;

                    Lastselected:=lastselected+1;

                    if FirstShiftSelected<lastselected then
                      for i:=FirstShiftselected to lastselected do selected[i]:=true
                    else
                      for i:=FirstShiftSelected downto lastselected do selected[i]:=true;
                  end;
                end
                else
                begin
                  if lastselected<numberofRecords-1 then
                  begin
                    for i:=0 to numberofRecords-1 do selected[i]:=false;
                    Lastselected:=Lastselected+1;
                    selected[LastSelected]:=true;
                  end;
                end;

                if lastselected<scrollbar1.position then scrollbar1.Position:=lastselected;
                if lastselected>=scrollbar1.position+(numberoflines-1) then
                begin
                  //if it it more then 2/3th visible select it, else increase the scroller
                  //every line is 16 pixels
                  if (panel3.height mod 16)<10 then
                    scrollbar1.Position:=lastselected-(numberoflines-2)
                  else
                    scrollbar1.Position:=lastselected-(numberoflines-1);

                end;

                Updatescreen;

              end;

    vk_prior:  begin  //page up
                if not ((ssShift) in (Shift)) then FirstShiftSelected:=-1;

                if ssShift in Shift then  //ctrl does nothing
                begin
                  if lastselected>0 then
                  begin
                    if FirstShiftSelected=-1 then FirstShiftSelected:=lastselected;

                    //select everything from FirstShiftSelected to sel
                    for i:=0 to numberofrecords-1 do selected[i]:=false;

                    if LastSelected>(numberoflines-1) then
                      Lastselected:=lastselected-numberoflines
                    else
                      LastSelected:=0;



                    if FirstShiftSelected<lastselected then
                      for i:=FirstShiftselected to lastselected do selected[i]:=true
                    else
                      for i:=FirstShiftSelected downto lastselected do selected[i]:=true;

                  end;
                end
                else
                begin
                  if lastselected>0 then
                  begin
                    for i:=0 to numberofRecords-1 do selected[i]:=false;
                    if lastselected>(numberoflines-1) then
                      Lastselected:=lastselected-numberoflines
                    else
                      LastSelected:=0;
                    selected[lastselected]:=true;
                  end;
                end;

                if lastselected<scrollbar1.position then scrollbar1.Position:=lastselected;
                if lastselected>scrollbar1.position+(numberoflines-1) then scrollbar1.Position:=lastselected-(numberoflines-1);

                Updatescreen;

               end;

    vk_next:   begin  //page down
                if not ((ssShift) in (Shift)) then FirstShiftSelected:=-1;

                if ssShift in Shift then  //ctrl does nothing
                begin
                  if lastselected<numberofRecords-1 then
                  begin
                    if FirstShiftSelected=-1 then FirstShiftSelected:=lastselected;

                    //select everything from FirstShiftSelected to sel
                    for i:=0 to numberofrecords-1 do selected[i]:=false;

                    if Lastselected+(numberoflines-1)<numberofrecords-1 then
                      Lastselected:=lastselected+(numberoflines-1)
                    else
                      Lastselected:=Numberofrecords-1;


                    if FirstShiftSelected<lastselected then
                      for i:=FirstShiftselected to lastselected do selected[i]:=true
                    else
                      for i:=FirstShiftSelected downto lastselected do selected[i]:=true;
                  end;
                end
                else
                begin
                  if lastselected<numberofRecords-1 then
                  begin
                    for i:=0 to numberofRecords-1 do selected[i]:=false;

                    if Lastselected+(numberoflines-1)>NumberOfRecords-1 then
                      Lastselected:=Numberofrecords-1
                    else
                      LastSelected:=Lastselected+(numberoflines-1);

                    selected[LastSelected]:=true;
                  end;
                end;

                if lastselected<scrollbar1.position then scrollbar1.Position:=lastselected;
                if lastselected>scrollbar1.position+(numberoflines-1) then scrollbar1.Position:=lastselected-(numberoflines-1);

                Updatescreen;
               end;

    vk_delete: begin
                 if editingscript then exit;

                 Deletethisrecord1.Click;
               end;

    vk_space:  begin
                 //(un)freeze all selected addresses
                 //according to the lastselected one, AND if shift/ctrl is presses
                 FreezeOrUnfreezeSelected;

               end;

    vk_add:    begin
                 if [ssctrl] = shift then
                 begin
                   //move selected records one pos down
                   if (lastselected<>-1) and (lastselected<numberofrecords) then
                   begin
                     if not selected[lastselected] then exit;
                     
                     for i:=0 to numberofrecords-1 do
                       selected[i]:=false;

                     selected[lastselected]:=true;
                     CopySelectedRecords;
                     DeleteRecords;

                     lastselected:=paste(true);

                     for i:=0 to numberofrecords-1 do
                       selected[i]:=false;

                     selected[lastselected]:=true;
                     updatescreen;
                   end;

                 end
                 else
                 begin
                   FreezeOrUnfreezeSelected;

                   for i:=0 to numberofrecords-1 do
                   begin
                     if (hotkeys[i]=-1) and (selected[i]) then
                     begin
                       memrec[i].Frozendirection:=2;
                       memrec[i].Frozen:=true;
                     end;
                   end;

                   updatescreen;
                   updatelist;
                 end;



               end;

    vk_subtract:
               begin
                 if [ssctrl] = shift then
                 begin
                   //move selected records one pos up
                   if (lastselected<>-1) and (lastselected<numberofrecords) then
                   begin
                     if (lastselected=0) or (not selected[lastselected]) then exit;

                     for i:=0 to numberofrecords-1 do
                       selected[i]:=false;

                     dec(lastselected); //cheat, just move the previous one up
                     
                     selected[lastselected]:=true;
                     CopySelectedRecords;
                     DeleteRecords;

                     lastselected:=paste(true)-1;

                     for i:=0 to numberofrecords-1 do
                       selected[i]:=false;

                     selected[lastselected]:=true;
                     updatescreen;
                   end;

                 end
                 else
                 begin
                   FreezeOrUnfreezeSelected;

                   for i:=0 to numberofrecords-1 do
                   begin
                     if (hotkeys[i]=-1) and (selected[i]) then
                     begin
                       memrec[i].Frozendirection:=1;
                       memrec[i].Frozen:=true;
                     end;
                   end;

                   updatescreen;
                   updatelist;
                 end;
               end;


  end;
  key:=0;

end;

procedure TMainForm.ScrollBar1Enter(Sender: TObject);
begin
  FControl.SetFocus;
end;

procedure TMainForm.FControlExit(Sender: TObject);
begin
  LastLastSelected:=LastSelected;
  Lastselected:=-1;
  Updatescreen;
end;

procedure TMainForm.Panel1Click(Sender: TObject);
begin
  FControl.SetFocus;
end;

procedure TMainForm.FControlEnter(Sender: TObject);
begin
  LastSelected:=LastLastSelected;
  Updatescreen;
end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
var i: integer;
   reg: Tregistry;
   crashcounter: integer;
begin
  //close codefinder
  if foundcodedialog<>nil then
  begin
    foundcodedialog.btnOK.Click;  //first or 2nd click
    if foundcodedialog<>nil then
      foundcodedialog.btnOK.Click; //2nd click
  end;

  //undo unrandomize
  if unrandomize<>nil then
    freeandnil(unrandomize);

  numberofrecords:=0;
  reservemem;

  cbSpeedhack.Checked:=false;
  cbFasterscan.Checked:=false;

  if flashprocessbutton<>nil then
    flashprocessbutton.Terminate;
 {
  if debuggerthread2<>nil then
    freeandnil(debuggerthread2); }

  try
  if @DebugActiveProcessStop<>@DebugActiveProcessStopProstitute then
  begin
    //detach the debugger
    hide;
    crashcounter:=0;
    if advancedoptions.Pausebutton.Down then
    begin
      advancedoptions.Pausebutton.Down:=false;
      advancedoptions.Pausebutton.Click;
    end;


    if debuggerthread<>nil then debuggerthread.Terminate;
    while (debuggerthread<>nil) and (debuggerthread.attached) and (crashcounter<10) do
    begin
      inc(crashcounter);
      sleep(1000);
    end;
  end;
  except
    //
  end;

  if frmProcessWatcher<>nil then
  begin
    frmProcessWatcher.Free;
    frmProcessWatcher:=nil;
  end;


  try
  tempbitmap.free;
  shutdown;
  closehandle(debugger.semaphore);
  unregisterhotkey(handle,0);


  for i:=0 to numberofrecords-1 do
    if hotkeys[i]<>-1 then unregisterhotkey(handle,hotkeys[i]);
  except
    //
  end;

  if advancedoptions.Pausebutton.Down then
  begin
    with advancedoptions do
    begin
      pausebutton.down:=not pausebutton.down;
      pausebutton.Click;
    end;
  end;

  if length(windowlist)>0 then
  begin
    toggleWindow;
    setforegroundwindow(lastforeground);
    setactivewindow(lastactive);
  end;

  autoattachlist.free;
  if speedhack<>nil then speedhack.free;
 // EExternalException
end;


procedure TMainForm.CommentButtonClick(Sender: TObject);
begin
  comments.Show;
end;

procedure TMainForm.CommentButtonMouseMove(Sender: TObject;
  Shift: TShiftState; X, Y: Integer);
begin
  if comments.Memo1.Lines.Count=0 then
  begin
    Commentbutton.Hint:='No Comments';
    exit;
  end;

  Commentbutton.Hint:=copy(comments.Memo1.Text,1,20);
  if length(comments.Memo1.Text)>20 then Commentbutton.Hint:=Commentbutton.Hint+'...';
end;

procedure TMainForm.SettogroupXClick(Sender: TObject);
var groupnr: Integer;
    i: Integer;
begin
  //set all selected items to group (Sender as TmenuItem).tag
  GroupNr:=(Sender as TMenuItem).Tag;
  for i:=0 to numberofrecords-1 do
    if selected[i] then memrec[i].group:=Groupnr;

  updatescreen;
end;

procedure TMainForm.Settonogroup1Click(Sender: TObject);
begin
  memrec[lastselected].Group:=0;
end;

procedure TMainForm.SetPrioritys1Click(Sender: TObject);
begin
  formsettings.showmodal;
end;

procedure TMainForm.copySelectedRecords;
var clip: TClipboard;
    textform: string;
    i,j:  Integer;
    nrselected: integer;

    ms: tmemorystream;

    identifier: string;
    x: dword;
    hentries: thandle;

    targetbuffer: pointer;

    doc: TXMLDocument;
    CheatTable: IXMLNode;
    Entries: IXMLNode;
begin
  if editingscript then exit; //don't do it when editing a script

  doc:=TXMLDocument.Create(application);
  try
    doc.Options:=doc.Options+[doNodeAutoIndent];
    doc.Active:=true;
    CheatTable:=doc.AddChild('CheatTable');
    Entries:=CheatTable.AddChild('CheatEntries');

    for i:=0 to numberofrecords-1 do
      if selected[i] then
        SaveCTEntryToXMLNode(i,entries);

    Clipboard.SetTextBuf(pchar(doc.XML.Text));
  finally
    doc.free;
  end;


  {

  if openclipboard(handle) then
  begin
    emptyclipboard;
    //fill the memorystream with the required data
    ms:=tmemorystream.Create;

    try
      ms.WriteBuffer('CETables',8);
      x:=copypasteversion;
      ms.WriteBuffer(x,sizeof(x));

      nrselected:=0;
      for i:=0 to numberofrecords-1 do
        if selected[i] then inc(nrselected);
      ms.WriteBuffer(nrselected,sizeof(nrselected));

      for i:=0 to numberofrecords-1 do
      begin
        if selected[i] then
        begin
          //description
          x:=length(memrec[i].description);
          ms.WriteBuffer(x,sizeof(x));
          ms.WriteBuffer(memrec[i].description[1],x);

          //address
          ms.WriteBuffer(memrec[i].address,sizeof(memrec[i].address));

          //interpretable address
          x:=length(memrec[i].interpretableaddress);
          ms.writebuffer(x,sizeof(x));
          ms.writebuffer(memrec[i].interpretableaddress[1],x);

          //vartype
          ms.WriteBuffer(memrec[i].VarType,sizeof(memrec[i].VarType));

          //unicode
          ms.WriteBuffer(memrec[i].unicode,sizeof(memrec[i].unicode));

          //IsPointer
          ms.writebuffer(memrec[i].IsPointer,sizeof(memrec[i].IsPointer));

          //pointers
          x:=length(memrec[i].pointers);
          ms.WriteBuffer(x,sizeof(x));
          for j:=0 to x-1 do
          begin
            //address
            ms.writebuffer(memrec[i].pointers[j].Address,sizeof(memrec[i].pointers[j].Address));

            //offset
            ms.writebuffer(memrec[i].pointers[j].offset,sizeof(memrec[i].pointers[j].offset));

            //interpretable address
            x:=length(memrec[i].pointers[j].Interpretableaddress);
            ms.writebuffer(x,sizeof(x));
            ms.writebuffer(memrec[i].pointers[j].interpretableaddress[1],x);
          end;

          //bit
          ms.WriteBuffer(memrec[i].Bit,sizeof(memrec[i].bit));

          //bitlength
          ms.writebuffer(memrec[i].bitlength,sizeof(memrec[i].bitlength));

          //skip frozen (always false)

          //showashex
          ms.writebuffer(memrec[i].ShowAsHex,sizeof(memrec[i].ShowAsHex));

          //autoassemble script
          x:=length(memrec[i].autoassemblescript);
          ms.writebuffer(x,sizeof(x));
          ms.writebuffer(memrec[i].autoassemblescript[1],x);
        end;
      end;

      //the stream has been filled, now globalalloc with ms.size as size
      hentries := GlobalAlloc(GMEM_DDESHARE or GMEM_MOVEABLE,ms.Size);
      targetbuffer:=globallock(hentries);
      copymemory(targetbuffer,ms.Memory,ms.size);
      globalunlock(hentries);

      SetclipboardData(ceclipboardformat,hentries);

    finally
      ms.free;
      closeclipboard;
    end;
  end;     }
end;

function TMainform.paste(simplecopypaste: boolean): integer;
{
this routine will paste a entry from the cplipboard into the addresslist of CE
If simplecopypaste is false frmPasteTableentry is shown to let the user change
some stuff before adding the new entry

returns the entry number of the new addresses (first one)
}
var clip: TClipboard;
    textform,y: string;
    textform2: Pchar;
    i,j,k,l: Integer;
    last: Integer;
    temprec: array of memoryRecord;

    first:boolean;
    lines:array of string;
    linenr: integer;
    temp: dword;

    records: integer;

    stringnr: integer;

    texthandle: thandle;
    textformpos: integer;

    ms: tmemorystream;
    hentries: thandle;
    sourcebuffer: pointer;

    p: pchar;
    x: dword;

    replace_find: string;
    replace_with: string;
    changeoffsetstring: string;
    changeoffset: dword;


    doc: TXMLDocument;
    CheatTable: IXMLNode;
    entries: IXMLNode;
    CheatEntry: IXMLNode;

    buf: string;
begin
  if editingscript then exit; //don't do it when editing a script

  k:=0;

  ms:=tmemorystream.Create;
  doc:=TXMLDocument.Create(application);
  try
    try
      buf:=clipboard.AsText;
      ms.WriteBuffer(buf[1],length(buf));

      doc.LoadFromStream(ms);

      doc.Active;


      CheatTable:=doc.ChildNodes.FindNode('CheatTable');
      if cheattable<>nil then
      begin
        Entries:=cheattable.ChildNodes.FindNode('CheatEntries');
        if entries<>nil then
        begin
          k:=entries.ChildNodes.Count;
          setlength(temprec, k);

          if k>0 then
          begin
            //valid table
            frmPasteTableentry:=TfrmPasteTableentry.create(self);
            try
              if not simplecopypaste then
                if frmpastetableentry.showmodal=mrcancel then exit;

              replace_find:=frmpastetableentry.edtFind.text;
              replace_with:=frmpastetableentry.edtReplace.text;
              changeoffsetstring:='$'+stringreplace(frmpastetableentry.edtOffset.Text,'-','-$',[rfReplaceAll]);
              changeoffsetstring:=stringreplace(changeoffsetstring,'$-','-',[rfReplaceAll]);
              try
                changeoffset:=strtoint(changeoffsetstring);
              except
                changeoffset:=0;
              end;

            finally
              freeandnil(frmPasteTableentry);
            end;



            for i:=0 to k-1 do
            begin
              CheatEntry:=entries.ChildNodes[i];

              temprec[i]:=GetmemrecFromXMLNode(CheatEntry);

              if not simplecopypaste then
              begin
                if replace_find<>'' then
                  temprec[i].Description:=stringreplace(temprec[i].Description,replace_find,replace_with,[rfReplaceAll,rfIgnoreCase]);

                temprec[i].Address:=temprec[i].address+changeoffset;
                if temprec[i].interpretableaddress<>'' then
                begin
                  try
                    x:=symhandler.getAddressFromName(temprec[i].interpretableaddress);
                    x:=x+changeoffset;
                    temprec[i].interpretableaddress:=symhandler.getNameFromAddress(x,true,true)
                  except
                    temprec[i].interpretableaddress:=inttohex(temprec[i].Address,8);
                  end;
                end;
              end;

            end;
          end;
        end;
      end;


      inc(NumberOfRecords,k);
      ReserveMem;

    finally
      doc.free;
      ms.free;
    end;
  except
    exit;
  end;


  result:=lastselected+1;

  for i:=numberofrecords-k-1 downto lastselected+1 do
  begin
    memrec[i+k]:=memrec[i];
    selected[i+k]:=selected[i];
    frozenfvalue[i+k]:=frozenfvalue[i];
    frozenstrings[i+k]:=frozenstrings[i];
    frozenbytes[i+k]:=frozenbytes[i];
    hotkeystrings[i+k]:=hotkeystrings[i];
    hotkeys[i+k]:=hotkeys[i];

  end;

  if numberofrecords-k=0 then
  for i:=0 to k-1 do
  begin
    memrec[i]:=temprec[i];
    hotkeys[i]:=-1;
    selected[i]:=false;
  end
  else
  for i:=lastselected+1 to lastselected+k do
  begin
    memrec[i]:=temprec[i-lastselected-1];
    hotkeys[i]:=-1;
    selected[i]:=false;
  end;

  mainform.UpdateScreen;
  mainform.Updatelist;

end;

procedure TMainForm.Copy1Click(Sender: TObject);
begin
  copyselectedrecords;
end;

procedure TMainForm.Cut1Click(Sender: TObject);
begin
  copyselectedrecords;
  deleterecords;
  updatescreen;
  updatelist;
end;

procedure TMainForm.Paste1Click(Sender: TObject);
begin
  Paste(formsettings.cbsimplecopypaste.checked);
  updatescreen;
  updatelist;
end;

procedure TMainForm.Panel1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var i: Integer;
begin
  if not ((ssSHift in Shift) or (ssCtrl in Shift)) then
  begin
    for i:=0 to numberofrecords-1 do
    begin
      selected[i]:=false;
    end;
    updatescreen;
  end;
end;

procedure TMainForm.Sortaddressesbygroup1Click(Sender: TObject);
var temprec: memoryrecord;
    i,j:       Integer;
    smallest: Integer;
    TempSelected: boolean;
    TempFvalue: double;
    TempString: string;
begin
//sort memrec by frozen

  for i:=0 to numberofrecords-1 do
    begin
      smallest:=i;
      for j:=i to numberofrecords-1 do  //find here the smallest
        if memrec[j].group<memrec[smallest].group then smallest:=j;
      temprec:=memrec[i];
      memrec[i]:=memrec[smallest];
      memrec[smallest]:=temprec;

      tempfvalue:=FrozenFvalue[i];
      FrozenFvalue[i]:=FrozenFvalue[smallest];
      FrozenFvalue[smallest]:=tempFvalue;

      tempstring:=frozenstrings[i];
      frozenstrings[i]:=frozenstrings[smallest];
      frozenstrings[smallest]:=tempstring;

      if (selected[i]) or (selected[smallest]) then
      begin
        tempselected:=selected[i];
        selected[i]:=selected[smallest];
        selected[smallest]:=tempselected;
      end;

      if (i=lastselected) then LastSelected:=smallest;
      If (smallest=lastselected) then lastselected:=i;

    end;

  updatescreen;
  FControl.SetFocus;

end;

procedure TMainForm.Setbreakpoint1Click(Sender: TObject);
resourcestring
  strFindWhatWritesToPointer='Find out what writes to this pointer';
  strFindWhatWritesToPointer2='Find what reads from the address pointed at by this pointer';
  strcantdebugnow='You can''t use this function while you are debugging the application yourself. (Close the memory view window)';
  strpointercantberead='The pointer can''t be completly read';
var address: dword;
    realaddress,realaddress2,count: dword;
    j: integer;
    res:word;
    check: boolean;
begin
  if (not formsettings.cbKdebug.checked) then
  begin
    if (not startdebuggerifneeded) then exit;
    if debuggerthread.userisdebugging then raise exception.create(strcantdebugnow);
  end;

  address:=memrec[lastselected].Address;

  if memrec[lastselected].IsPointer then
  begin
    address:=memrec[lastselected].pointers[length(memrec[lastselected].pointers)-1].Address;
    with TformPointerOrPointee.create(self) do
    begin
      button1.Caption:=strfindwhatwritestopointer;
      button2.Caption:=strfindwhatwritestopointer2;
      res:=showmodal;
      if res=mrno then
      begin
        //find what writes to the address pointer at by this pointer
        realaddress2:=memrec[lastselected].pointers[length(memrec[lastselected].pointers)-1].Address;
        for j:=length(memrec[lastselected].pointers)-1 downto 0 do
        begin
          check:=readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count);
          if check and (count=4) then
            realaddress2:=realaddress+memrec[lastselected].pointers[j].offset
          else
            raise exception.Create(strpointercantberead);
        end;
        address:=realaddress2;

      end
      else if res=mryes then address:=memrec[lastselected].pointers[length(memrec[lastselected].pointers)-1].Address else exit;
    end;
  end;

  if memrec[lastselected].VarType=0 then SetWriteBreakpoint(address,1); //byte
  if memrec[lastselected].VarType=1 then SetWriteBreakpoint(address,2); //word
  if memrec[lastselected].VarType=2 then SetWriteBreakpoint(address,4); //dword
  if memrec[lastselected].VarType=3 then SetWriteBreakpoint(address,4); //single
  if memrec[lastselected].VarType=4 then SetWriteBreakpoint(address,8); //double
  if memrec[lastselected].VarType=5 then SetWriteBreakpoint(address,1+(memrec[lastselected].Bit+memrec[lastselected].bitlength) div 8); //bit(will be handled as a byte)
  if memrec[lastselected].VarType=6 then SetWriteBreakpoint(address,8); //8-bytes (qword)
  if memrec[lastselected].VarType=7 then SetWriteBreakpoint(address,memrec[lastselected].Bit); //length of the text
  if memrec[lastselected].VarType=8 then SetWriteBreakpoint(address,memrec[lastselected].Bit); //length of the array

end;

procedure TMainForm.TopDisablerTimer(Sender: TObject);
begin
  setwindowpos(mainform.Handle,HWND_NOTOPMOST,mainform.left,mainform.top,mainform.width,mainform.height,SWP_SHOWWINDOW);
  TopDisabler.Enabled:=false;
end;

procedure Tmainform.ResizeScreen;
var i: integer;
    previouscount: integer;
    changed:boolean;
    FrozenWidth, DescriptionWidth, AddressWidth, typeWidth, ValueWidth: integer;
    FrozenLeft, DescriptionLeft, AddressLeft, typeLeft, ValueLeft: integer;
begin
  FrozenWidth:=headercontrol1.sections[0].width;
  descriptionwidth:=headercontrol1.sections[1].width;
  addresswidth:=headercontrol1.sections[2].width;
  typewidth:=headercontrol1.sections[3].width;
  valuewidth:=headercontrol1.sections[4].width;

  FrozenLeft:=headercontrol1.sections[0].left+2;
  descriptionleft:=headercontrol1.sections[1].left+2;
  addressleft:=headercontrol1.sections[2].left+2;
  typeleft:=headercontrol1.sections[3].left+2;
  valueleft:=headercontrol1.sections[4].left+2;

  //now addjust the numberoflines and create rows if needed
  //every row is 16 pixels so just do
  previouscount:=numberoflines;

  for i:=0 to previouscount-1 do
  begin
    if description[i].Left<>descriptionleft then
      description[i].Left:=descriptionleft;

    if description[i].Width<>descriptionwidth then
      description[i].Width:=descriptionwidth;

    if address[i].Left<>addressleft then
      address[i].Left:=addressleft;

    if address[i].Width<>addresswidth then
      address[i].Width:=addresswidth;


    if valtype[i].Left<>typeleft  then
      ValType[i].Left:=typeleft;

    if ValType[i].Width<>Typewidth then
      ValType[i].Width:=Typewidth;


    if value[i].Left<>valueleft then
      Value[i].Left:=valueleft;

    if value[i].Width<>valuewidth then
      value[i].Width:=valuewidth;

   // freezedirection[i].Left:=frozenoffset+2;
  end;



  numberoflines:=(panel3.height div 16) +1;

  if length(select) < numberoflines then
  begin
    //make new lines
    setlength(frozenbox,numberoflines);
    setlength(description,numberoflines);
    setlength(address,numberoflines);
    setlength(ValType,numberoflines);
    setlength(Value,numberoflines);
    setlength(Select,numberoflines);
    setlength(freezedirection,numberoflines);


    for i:=previouscount to numberoflines-1 do
    begin
      //checkbox
      select[i]:=Tlabel.Create(self);

      select[i].AutoSize:=false;
      select[i].Color:=select[0].Color;
      select[i].Top:=i*16;
      select[i].Left:=0;
      select[i].Width:=panel3.Width;
      select[i].Height:=16;
      select[i].Anchors:=[akLeft,akTop,akRight];

      select[i].Caption:=select[0].Caption;
      select[i].Transparent:=false;
      select[i].Visible:=true;
      select[i].tag:=i;
      select[i].SendToBack;
      select[i].Font:=select[0].Font;

      select[i].ParentColor:=false;
      select[i].ParentFont:=false;
      select[i].OnDragDrop:=Panel1DragDrop;
      select[i].OnDragOver:=panel1DragOver;
      select[i].OnMouseDown:=SlectItem; //damn spell error
      select[i].PopupMenu:=Popupmenu2;
      select[i].Parent:=panel3;


      frozenbox[i]:=tcheckbox.Create(self);
      frozenbox[i].Caption:='';
      frozenbox[i].Top:=i*16;
      frozenbox[i].Left:=frozenleft+22;
      frozenbox[i].Width:=17;
      frozenbox[i].Visible:=false;
      frozenbox[i].Tag:=i;
      frozenbox[i].Cursor:=crHandPoint;
      frozenbox[i].OnClick:=CheckBox1Click;
      frozenbox[i].OnDragDrop:=Panel1DragDrop;
      frozenbox[i].OnDragOver:=Panel1DragOver;
      frozenbox[i].OnMouseDown:=CheckBox2MouseDown;
      frozenbox[i].PopupMenu:=Popupmenu2;
      frozenbox[i].Parent:=panel3;

      description[i]:=Tlabel.Create(self);
      description[i].Font:=description[0].Font;
      description[i].Caption:='You shouldn''t be able to see this';
      description[i].Top:=i*16;
      description[i].Left:=descriptionleft;
      description[i].Visible:=false;
      description[i].Tag:=i;
      description[i].transparent:=true;
      description[i].Cursor:=crHandPoint;
      description[i].OnDblClick:=Label28Click;
      description[i].OnDragDrop:=Panel1DragDrop;
      description[i].OnDragOver:=panel1DragOver;
      description[i].OnMouseDown:=Slectitem;

      description[i].PopupMenu:=popupmenu2;
      description[i].Parent:=panel3;

      address[i]:=Tlabel.Create(self);
      address[i].Top:=i*16;
      address[i].Left:=addressleft;
      address[i].Visible:=false;
      address[i].Tag:=i;
      address[i].Transparent:=true;
      address[i].Cursor:=crHandPoint;
      address[i].OnDblClick:=Addressclick;
      address[i].OnDragDrop:=Panel1DragDrop;
      address[i].OnDragOver:=panel1DragOver;
      address[i].OnMouseDown:=Slectitem;

      address[i].PopupMenu:=popupmenu2;
      address[i].Parent:=panel3;

      ValType[i]:=Tlabel.Create(self);
      ValType[i].Top:=i*16;
      ValType[i].Left:=typeleft;
      valtype[i].Width:=typewidth;
      ValType[i].Visible:=false;
      valtype[i].Tag:=i;
      valtype[i].Transparent:=true;
      valtype[i].Cursor:=crHandPoint;
      valtype[i].OnDblClick:=TypeClick;
      valtype[i].OnDragDrop:=Panel1DragDrop;
      valtype[i].OnDragOver:=panel1DragOver;
      valtype[i].OnMouseDown:=Slectitem;
      valtype[i].PopupMenu:=popupmenu2;
      ValType[i].Parent:=panel3;


      Value[i]:=Tlabel.Create(self);
      Value[i].Top:=i*16;
      Value[i].Left:=valueleft;
      value[i].Width:=valuewidth;
      Value[i].Visible:=false;
      value[i].Tag:=i;
      value[i].Transparent:=true;
      value[i].Cursor:=crHandPoint;
      value[i].OnDblClick:=valueclick;
      value[i].OnDragDrop:=Panel1DragDrop;
      value[i].OnDragOver:=panel1DragOver;
      value[i].OnMouseDown:=Slectitem;
      value[i].PopupMenu:=popupmenu2;
      Value[i].Parent:=panel3;

      freezedirection[i]:=TLabel.create(self);
      freezedirection[i].Caption:='';
      freezedirection[i].Font.Color:=clRed;
      freezedirection[i].Font.Style:=[fsBold];
      freezedirection[i].Font.Size:=12;

      freezedirection[i].Top:=-3+i*16;
      freezedirection[i].Left:=frozenleft+7;
      freezedirection[i].Visible:=false;
      freezedirection[i].ParentColor:=false;
      freezedirection[i].Tag:=i;
      freezedirection[i].Transparent:=true;
      freezedirection[i].OnMouseDown:=directionclick;
      freezedirection[i].OnDragDrop:=Panel1DragDrop;
      freezedirection[i].OnDragOver:=panel1DragOver;
      freezedirection[i].PopupMenu:=popupmenu2;
      freezedirection[i].Cursor:=crHandPoint;
      freezedirection[i].Parent:=panel3;

    end;
  end;
          
  updatescreen;
end;

procedure TMainForm.Panel1Resize(Sender: TObject);
begin
  resizescreen;
end;

procedure TMainForm.ScrollBar1Scroll(Sender: TObject;
  ScrollCode: TScrollCode; var ScrollPos: Integer);
begin
  //bugfix? (I cant find a property in the scrollbar to do this correctly!)
//  if scrollpos>numberofrecords-(numberoflines-1) then scrollpos:=numberofrecords-(numberoflines-1);
end;

procedure TMainForm.advancedbuttonClick(Sender: TObject);
begin

  advancedoptions.Show;
end;




procedure TMainForm.HexadecimalCheckboxClick(Sender: TObject);
var x: int64;
    i: integer;
begin
  if dontconvert then exit;
{  if VarType.Text='Byte' then    getVarType:=0 else
  if VarType.Text='2 Bytes' then getVarType:=1 else
  if VarType.Text='4 Bytes' then getVarType:=2 else
  if VarType.Text='8 Bytes' then getvarType:=6 else
  if Vartype.Text='Float' then   getVarType:=3 else
  if Vartype.Text='Double' then  getVarType:=4 else
  if VarType.Text='Bit' then     getVarType:=5 else
  if vartype.Text='Text'then     getVarType:=7 else
  if vartype.Text='Array of Bytes' then getVarType:=8 else}

  if HexadecimalCheckbox.Checked then
  begin
    //convert what is in scanvalue to hexadecimal notation
    val(scanvalue.Text,x,i);
    case GetVarType of
      0: scanvalue.text:=IntToHex(byte(x),2);
      1: scanvalue.Text:=inttohex(word(x),4);
      2: scanvalue.Text:=inttohex(dword(x),8);
      6: scanvalue.Text:=inttohex(int64(x),16);
    end;

  end
  else
  begin
    //convert to decimal noatation
    case GetVarType of
      0,1,2,6: begin
                 if length(scanvalue.Text)>0 then
                 begin
                   if scanvalue.Text[1]='-' then
                     val('-$'+copy(scanvalue.Text,2,length(scanvalue.text)),x,i)
                   else
                     val('$'+scanvalue.Text,x,i);

                   scanvalue.Text:=inttostr(x);
                 end;
               end;
    end;
  end;
end;

procedure TMainForm.SetHotkey1Click(Sender: TObject);
var db: Byte;
    dw: Word;
    dd: dword;
    di64: Int64;
    a: single;
    b: double;
    error: Dword;
    controle: string;
    temps: pchar;
    i,j,k: integer;
    read8: array of byte;
    read9: pbyte;
    temp: string;
    realaddress,realaddress2,count:dword;
    check: boolean;

    hotkeyvalue: string;
    hotkeydirection: integer;
    
begin
  HotKeyForm.recnr:=lastselected;


  if hotkeys[lastselected]<>-1 then //remove this hotkey
  begin
    memrec[lastselected].Frozendirection:=0;
    unregisterhotkey(handle,hotkeys[lastselected]);
    hotkeys[lastselected]:=-1;
    updatescreen;
    exit;
  end;

  if memrec[lastselected].IsPointer then
  begin
    //find the real address
    realaddress2:=memrec[lastselected].pointers[length(memrec[lastselected].pointers)-1].Address;
    for j:=length(memrec[lastselected].pointers)-1 downto 0 do
    begin
      check:=readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count);
      if check and (count=4) then
        realaddress2:=realaddress+memrec[lastselected].pointers[j].offset;
    end;
    realaddress:=realaddress2;
  end else realaddress:=memrec[lastselected].Address;




  hotKeyForm.hotkeyvalue:=value[lastselected-scrollbar1.position].Caption;

  if memrec[lastselected].VarType=255 then
    hotkeyform.autoassemble:=true
  else
    hotkeyform.autoassemble:=false;

  error:=0;
  if HotKeyForm.showModal=mrok then
  begin
    memrec[lastselected].Frozen:=false;

    //hotkeyform2
    memrec[lastselected].Frozendirection:=hotkeyform.freezedirection;

    case memrec[lastselected].VarType of
      0:      begin  //byte
                readprocessmemory(processhandle,pointer(realaddress),addr(db),1,error);
                if error=1 then
                begin
                  db:=strtoint(hotkeyform.hotkeyvalue);
                  memrec[lastselected].FrozenValue:=db;
                end
                else
                begin
                  unregisterhotkey(Handle,hotkeys[lastselected]);
                  hotkeys[lastselected]:=-1;
                end;
              end;

      1:      begin  //word
                readprocessmemory(processhandle,pointer(realaddress),addr(dw),2,error);
                if error=2 then
                begin
                  dw:=strtoint(hotkeyform.hotkeyvalue);
                  memrec[lastselected].FrozenValue:=dw
                end
                else
                begin
                  unregisterhotkey(Handle,hotkeys[lastselected]);
                  hotkeys[lastselected]:=-1;
                end;
              end;

      2:      begin  //dword
                readprocessmemory(processhandle,pointer(realaddress),addr(dd),4,error);
                if error=4 then
                begin
                  dd:=strtoint(hotkeyform.hotkeyvalue);
                  memrec[lastselected].FrozenValue:=dd
                end
                else
                begin
                  unregisterhotkey(Handle,hotkeys[lastselected]);
                  hotkeys[lastselected]:=-1;
                end;
              end;

      3:      begin
                readprocessmemory(processhandle,pointer(realaddress),addr(a),4,error);
                if error=4 then
                begin
                  controle:=FloatToStr(a);
                  if (system.pos('NAT',controle)>0) or (system.pos('INF',controle)>0) then
                  begin
                    unregisterhotkey(Handle,hotkeys[lastselected]);
                    hotkeys[lastselected]:=-1;
                  end;

                  a:=strtofloat(hotkeyform.hotkeyvalue);
                  frozenfvalue[lastselected]:=a;
                end
                else
                begin
                  unregisterhotkey(Handle,hotkeys[lastselected]);
                  hotkeys[lastselected]:=-1;
                end;
              end;

      4:      begin
                readprocessmemory(processhandle,pointer(realaddress),addr(b),8,error);
                if error=8 then
                begin
                  controle:=FloatToStr(b);
                  if (system.pos('NAT',controle)>0) or (system.pos('INF',controle)>0) then
                  begin
                    unregisterhotkey(Handle,hotkeys[lastselected]);
                    hotkeys[lastselected]:=-1;
                  end;

                  b:=strtofloat(hotkeyform.hotkeyvalue);
                  frozenfvalue[lastselected]:=b;
                end
                else
                begin
                  unregisterhotkey(Handle,hotkeys[lastselected]);
                  hotkeys[lastselected]:=-1;
                end;
              end;

      5:      begin  //binary
                k:=1+((memrec[i].Bit+memrec[i].bitlength) div 8);
                setlength(read8,k);

                readprocessmemory(processhandle,pointer(realaddress),addr(read8[0]),k,error);
                if error=k then
                begin
                  //find out the current bit combination (use frozenstrings to store the value)
                  //convert what i need to a string of bits
                  temp:='';
                  j:=memrec[i].Bit;
                  read9:=@read8[0];
                  for k:=1 to memrec[lastselected].bitlength do
                  begin
                    temp:=temp+IntToStr(getbit(j,read9^));
                    inc(j);
                    if j>=8 then
                    begin
                      j:=0;
                      inc(read9);
                    end;
                  end;

                  //the tempstring now contaisn the bits (bit0 is first char...)
                  frozenstrings[lastselected]:=temp;
                  memrec[lastselected].Frozen:=true;
                end;
              end;

      6:      begin  //int64
                readprocessmemory(processhandle,pointer(realaddress),addr(dI64),8,error);
                if error=8 then
                begin
                  di64:=strtoint64(hotkeyform.hotkeyvalue);
                  memrec[lastselected].FrozenValue:=di64
                end
                else
                begin
                  unregisterhotkey(Handle,hotkeys[lastselected]);
                  hotkeys[lastselected]:=-1;
                end;
              end;

      7:      begin  //text
                getmem(temps,memrec[lastselected].bit);
                readprocessmemory(processhandle,pointer(realaddress),temps,memrec[lastselected].Bit,error);
                if error=memrec[lastselected].bit then FrozenStrings[lastselected]:=temps
                else
                begin
                  unregisterhotkey(Handle,hotkeys[lastselected]);
                  hotkeys[lastselected]:=-1;
                end;
                freemem(temps);
              end;

      8:      begin  //array of byte
                setlength(FrozenBytes[lastselected],memrec[lastselected].bit);
                readprocessmemory(processhandle,pointer(realaddress),FrozenBytes[lastselected],memrec[lastselected].Bit,error);
                if error<>memrec[lastselected].bit then
                begin
                  unregisterhotkey(Handle,hotkeys[lastselected]);
                  hotkeys[lastselected]:=-1;
                end;
              end;

    end;

    updatescreen;
  end;
  
end;

procedure TMainForm.Findoutwhatreadsfromthisaddress1obsoleteClick(Sender: TObject);
var address: dword;
    realaddress,realaddress2,count: dword;
    j: integer;
    res:word;
    check: boolean;
begin
  exit;
  {
  if not startdebuggerifneeded then exit;
  if debuggerthread.userisdebugging then raise exception.create('You can''t use this function while you are debugging the application yourself. (Close the memory view window)');

  address:=memrec[lastselected].Address;

  if memrec[lastselected].IsPointer then
  begin
    address:=memrec[lastselected].pointers[length(memrec[lastselected].pointers)-1].Address;
    with TformPointerOrPointee.create(self) do
    begin
      res:=showmodal;
      if res=mrno then
      begin
        //find what writes to the address pointer at by this pointer
        realaddress2:=memrec[lastselected].pointers[length(memrec[lastselected].pointers)-1].Address;
        for j:=length(memrec[lastselected].pointers)-1 downto 0 do
        begin
          check:=readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count);
          if check and (count=4) then
            realaddress2:=realaddress+memrec[lastselected].pointers[j].offset;
        end;
        address:=realaddress2;

      end
      else if res=mryes then address:=memrec[lastselected].pointers[length(memrec[lastselected].pointers)-1].Address else exit;
    end;
  end;

  if memrec[lastselected].VarType=0 then SetReadBreakpoint(address,1); //byte
  if memrec[lastselected].VarType=1 then SetReadBreakpoint(address,2); //word
  if memrec[lastselected].VarType=2 then SetReadBreakpoint(address,4); //dword
  if memrec[lastselected].VarType=3 then SetReadBreakpoint(address,4); //single
  if memrec[lastselected].VarType=4 then SetReadBreakpoint(address,8); //double
  if memrec[lastselected].VarType=5 then SetReadBreakpoint(address,1+(memrec[lastselected].Bit+memrec[lastselected].bitlength) div 8); //bit(will be handled as a byte)
  if memrec[lastselected].VarType=6 then SetReadBreakpoint(address,8); //8-bytes (qword)
  if memrec[lastselected].VarType=7 then SetReadBreakpoint(address,memrec[lastselected].Bit); //length of the text
  if memrec[lastselected].VarType=8 then SetReadBreakpoint(address,memrec[lastselected].Bit); //length of the array
  }
end;

procedure TMainForm.UndoScanClick(Sender: TObject);
var i,j: integer;
    error: integer;
    a,b: string;
resourcestring
  strconfirmUndo='Do you really want to go back to the results of the previous scan?';
begin
  if messagedlg(strConfirmUndo,mtConfirmation	,[mbyes,mbno],0)=mryes then
  begin
    foundlist.Deinitialize;
    undolastscan(GetVarType,hexadecimalcheckbox.checked);
    foundcount:=foundlist.Initialize(getvartype);
    undoscan.Enabled:=false;
  end;
end;

procedure TMainform.adjustbringtofronttext;
var hotkey:string;
    reg : TRegistry;
resourcestring
  strHideForeground='will hide the foreground window';
  strHideAll='will hide all windows';
  strUnHideForeground='will bring the foreground window back';
  strUnhideAll='will bring all windows back';

begin
  if formsettings.cbHideAllWindows.Checked then
  begin
    if allwindowsareback then
    begin
      if onlyfront then fronttext:=strHideForeground
                   else fronttext:=strHideAll;
    end
    else
    begin
      if onlyfront then fronttext:=strUnhideForeground
                   else fronttext:=strUnhideAll;
    end;
  //
  end else fronttext:='brings Cheat Engine to front';



  try
    hotkey:='';
    reg:=TRegistry.Create;
    try
      Reg.RootKey := HKEY_CURRENT_USER;
      if Reg.OpenKey('\Software\Cheat Engine',false) then
        hotkey:=reg.ReadString('BringToFrontHotkey');
    except
    end;
  finally
    reg.Free;
  end;

  if hotkey='' then label7.caption:='';
//  fronthotkey:=hotkey;
end;

procedure TMainForm.FormShow(Sender: TObject);
resourcestring
  strhappybirthday='Let''s sing Happy Birthday for Dark Byte today!';
  strXMess='Have fun';
  strNewyear='And what are your good intentions for this year? ;-)';
  strfuture='Wow,I never imagined people would use Cheat Engine up to today';

var reg: tregistry;
    modifier: dword;
    key: dword;
    hotkey: string;
    year,month,day: word;
    temp:string;

    i: integer;
    outputfile: textfile;
    go:boolean;
    loadt: boolean;

    firsttime: boolean;
    x: array of integer;
begin
  Set8087CW($133f);
  loadt:=false;
  edit2.Text:=format('%.1f',[1.0]);

  reg:=Tregistry.Create;
  try
    Reg.RootKey := HKEY_CURRENT_USER;

    if not Reg.OpenKey('\Software\Cheat Engine',false) then
    begin
      if Reg.OpenKey('\Software\Cheat Engine',true) then
      begin
        //write some default data into the register
        reg.WriteBool('Undo',true);
        reg.writeBool('Advanced',true);
        reg.writeBool('SeperateThread',true);
        reg.writebool('Use Hyperscan if posible',false);

        reg.WriteInteger('ScanThreadpriority',formsettings.combothreadpriority.itemindex);
      end;
    end;
  except

  end;

  if reg.ValueExists('First Time User') then
    firsttime:=reg.ReadBool('First Time User')
  else
    firsttime:=true;

  if firsttime then
  begin
    reg.WriteBool('First Time User',false);

    if messagedlg('Do you want to try out the tutorial?',mtconfirmation,[mbyes,mbno],0)=mryes then
      shellexecute(0,'open','Tutorial.exe','','',sw_show);
  end;


//  animatewindow(mainform.Handle,10000,AW_CENTER);
  //mainform.repaint;
  fronttext:='brings Cheat engine to front';

  if dontrunshow then exit;

  panel7.DoubleBuffered:=true;
  flashprocessbutton:=tflash.create(false);



  dontrunshow:=true;
  decodedate(now,year,month,day);
  if (month=7) and (day=1) then showmessage(strhappybirthday);
  if (month=12) and ((day=25) or (day=26)) then Showmessage(strXmess);
  if (month=1) and (day=1) then showmessage(strnewyear );
  if (month=1) and (day=1) and (year>=2010) then showmessage(strFuture);

  if (month=4) and (day=1) then aprilfools:=true;

  if aprilfools=true then
    Messagedlg('Your license to use Cheat Engine has expired. You can buy a license to use cheat engine for 1 month for $200, 6 months for only $1000 and for 1 year for only $1800.'+' If you don''t renew your license Cheat Engine will be severely limited in it''s abilities. (e.g: Next scan has been disabled)',mtwarning,[mbok],0);

  LoadSettingsFromRegistry;

  //Load the table if one was suplied
  overridedebug:=false;
  if paramcount>=1 then
  begin
    loadt:=true;

    if uppercase(paramstr(1))='-O' then
    begin
      OverrideDebug:=true;
      loadt:=false;
    end;


    if paramcount>1 then
    begin
      //extra param
      temp:=paramstr(2);
      if length(temp)>4 then
      if temp[1]+temp[2]+temp[3]='/o=' then
      begin
        //output to:
        temp:=copy(temp,4,length(temp)-3);
        assignfile(outputfile,   temp);
        rewrite(outputfile);
        for i:=0 to numberofrecords-1 do
          writeln(outputfile,memrec[i].description+'   '+IntToHex(memrec[i].Address,8));

        closefile(outputfile);

        showmessage(temp+' has been created');
      end;
    end;
  end else
  begin

  end;

  if loadt then
  begin
    LoadTable(paramstr(1),false);
    updatescreen;
    updatelist;
  end;


  if GetSystemType<3 then //not a supported os for hardware breakpoints
  with formsettings do
  begin
    rdWriteExceptions.Checked:=true;
    rbDebugRegisters.Enabled:=false;
    label6.Enabled:=false;
    label7.Enabled:=false;

    rbDebugAsBreakpoint.Enabled:=false;
    rbInt3AsBreakpoint.Checked:=true;

  end;

  if (GetSystemType<4) {or (is64bitos)} then  //not nt or later
  begin
    with formsettings do
    begin
      cbKernelQueryMemoryRegion.enabled:=false;
      cbKernelReadWriteProcessMemory.enabled:=false;
      cbKernelOpenProcess.enabled:=false;
      cbProcessWatcher.Enabled:=false;
      cbKDebug.enabled:=false;
      cbGlobalDebug.enabled:=false;

      TauntOldOsUser.Visible:=true;
      label25.Enabled:=false;
    end;
  end;



  vartypechange(vartype);
  adjustbringtofronttext;


  if aprilfools then
    caption:=cenorm+' EXPIRED!';

  if autoattachtimer.enabled then autoattachcheck;




  //SMenu:=GetSystemMenu(handle,false);

  //don't put this in oncreate, just don't
  if memscan=nil then
    memscan:=tmemscan.create(progressbar1);

  memscan.setScanDoneCallback(mainform.handle,wm_scandone);

  FileAccessTest;    
                        
end;



procedure TMainForm.rbBitClick(Sender: TObject);
begin
   
  if not isbit then
  begin
    isbit:=true;
    //convert the value to a binary value
    try
      if scanvalue.text='' then scanvalue.text:='0' else
        scanvalue.text:=inttobin(strtoint(scanvalue.Text));
      if scanvalue.text='' then scanvalue.text:='0';
    except
     //
    end;
  end;

end;

procedure TMainForm.rbDecClick(Sender: TObject);
begin
  if isbit then
  begin
    isbit:=false;
    //convert the binary text to a decimal representation
    scanvalue.Text:=IntToStr(BinToInt(scanvalue.Text));
  end;
end;

procedure TMainForm.Cut2Click(Sender: TObject);
begin
  if scanvalue.SelLength>0 then
    scanvalue.CutToClipboard;
end;

procedure TMainForm.Copy2Click(Sender: TObject);
begin
  if scanvalue.SelLength>0 then
    scanvalue.CopyToClipboard;
end;

procedure TMainForm.Paste2Click(Sender: TObject);
var cb: TClipboard;
    text: string;
    i: integer;
    allow: boolean;
begin
  cb:=tclipboard.Create;
  if cb.HasFormat(CF_TEXT) then
  begin
    if scanvalue.Focused then
      scanvalue.PasteFromClipboard;

    if (scanvalue2<>nil) and (scanvalue2.Focused) then
      scanvalue2.PasteFromClipboard;
  end;

  cb.free;
end;

procedure TMainform.checkpaste;
var cb: TClipboard;
    text: string;
    i: integer;
    allow: boolean;
begin
  cb:=tclipboard.Create;
  Paste2.enabled:=cb.HasFormat(CF_TEXT);
  cb.free;
end;

procedure TMainForm.ccpmenuPopup(Sender: TObject);
begin
  checkpaste;
end;

procedure TMainForm.Splitter1CanResize(Sender: TObject;
  var NewSize: Integer; var Accept: Boolean);
begin
  if newsize<305 then
  begin
    newsize:=305;
    accept:=false;
  end; 
end;

procedure TMainForm.Splitter1Moved(Sender: TObject);
begin
  panel5.Repaint;
end;

procedure TMainForm.SettingsClick(Sender: TObject);
var tlhlp: thandle;
    m:tagMODULEENTRY32;
    mbi: _MEMORY_BASIC_INFORMATION;
    x:dword;
    i:integer;
    Savedata: tfilestream;


    ntdll,kernel32,user32:thandle;

    oldmodulelist:pointer;
begin
  suspendhotkeyhandler;

  oldmodulelist:=modulelist;

  if formsettings.ShowModal<>mrok then
  begin
    resumehotkeyhandler;
    LoadSettingsFromRegistry;
    exit;
  end;


  resumehotkeyhandler;

  //set the memorybrowser settings if they changed
  if formsettings.cbShowDisassembler.checked then
  begin
    memorybrowser.splitter1.Visible:=true;
    memorybrowser.panel1.Visible:=true;
  end
  else
  begin
  //  panel1.Visible:=false;
    memorybrowser.Panel1.Visible:=false;
    memorybrowser.splitter1.Visible:=false;
  end;


  if formsettings.cbKernelQueryMemoryRegion.checked then UseDBKQueryMemoryRegion else DontUseDBKQueryMemoryRegion;
  if formsettings.cbKernelReadWriteProcessMemory.checked then UseDBKReadWriteMemory else DontUseDBKReadWriteMemory;
  if formsettings.cbKernelOpenProcess.Checked then UseDBKOpenProcess else DontUseDBKOpenProcess;

  adjustbringtofronttext;
end;

procedure TMainForm.cbCaseSensitiveClick(Sender: TObject);
begin
  HexadecimalCheckbox.checked:=cbcasesensitive.Checked;
end;

procedure TMainForm.LogoMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if button=mbright then
    about1.click;
end;

var strt: integer=0;


procedure TMainForm.directionclick(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var sel: Integer;
    i: Integer;
begin
  FControl.SetFocus;


  sel:=0;
  if sender is TLabel then
  begin
    sel:=(Sender as TLabel).Tag+scrollbar1.Position;

    if sel>numberofrecords-1 then
    begin
      if not ((ssSHift in Shift) or (ssCtrl in Shift) or (ssRight in Shift)) then
      begin
        for i:=0 to numberofrecords-1 do
        begin
          selected[i]:=false;
        end;
        updatescreen;
      end;

      exit;
    end;

    if memrec[sel].Frozen then inc(memrec[sel].Frozendirection);
      
    if memrec[sel].Frozendirection=3 then memrec[sel].Frozendirection:=0;
  end;

  if not ((ssShift) in (Shift)) then FirstShiftSelected:=-1;

  if ssLeft in Shift then
  begin
    if not (ssShift in Shift) and not (ssCtrl in Shift) then
    begin
      for i:=0 to numberofrecords-1 do
        selected[i]:=false;
    end;

    if (sel>=numberofrecords) then
    begin
      updatelist;
      updatescreen;
      exit;
    end;

    if ssShift in shift then
    begin

      if FirstShiftSelected=-1 then FirstShiftSelected:=lastselected;

      //select everything from FirstShiftSelected to sel
      for i:=0 to numberofrecords-1 do selected[i]:=false;

      if FirstShiftSelected<sel then
        for i:=FirstShiftselected to sel do selected[i]:=true
      else
        for i:=FirstShiftSelected downto sel do selected[i]:=true;

      lastselected:=sel;

      updatelist;
      updatescreen;
      exit;
    end;


    if ssCtrl in shift then
    begin
      selected[sel]:=not selected[sel];
      if selected[sel] then lastselected:=sel;
      updatelist;
      updatescreen;
      exit;
    end;


    selected[sel]:=true;

  end;

  if ssRight in shift then
  begin
    if (sel>=numberofrecords) then
    begin
      updatelist;
      updatescreen;
      exit;
    end;

    if not selected[sel] then //clear all other selected items except this one
    begin
      for i:=0 to numberofrecords-1 do selected[i]:=false;
    end;

    selected[sel]:=true;

  end;

  lastselected:=sel;

  updatelist;
  Updatescreen;
end;

procedure TMainForm.btnShowRegionsClick(Sender: TObject);
begin
  formmemoryregions:=tformmemoryregions.Create(self);
  formmemoryregions.showmodal;
end;

procedure TMainForm.Findoutwhataccessesthisaddress1Click(Sender: TObject);
var address: dword;
    realaddress,realaddress2,count: dword;
    j: integer;
    res: word;
    check: boolean;
begin
  if (not formsettings.cbKdebug.checked) then
  begin
    if (not startdebuggerifneeded) then exit;
    //if debuggerthread.userisdebugging then raise exception.create('You can''t use this function while you are debugging the application yourself. (Close the memory view window)');
  end;

  address:=memrec[lastselected].Address;

  if memrec[lastselected].IsPointer then
  begin
    address:=memrec[lastselected].pointers[length(memrec[lastselected].pointers)-1].Address;
    with TformPointerOrPointee.create(self) do
    begin
      button1.Caption:='Find out what accesses this pointer';
      button2.Caption:='Find what accesses the address pointed at by this pointer';

      res:=showmodal;
      if res=mrno then
      begin
        //find what writes to the address pointer at by this pointer
        realaddress2:=memrec[lastselected].pointers[length(memrec[lastselected].pointers)-1].Address;
        for j:=length(memrec[lastselected].pointers)-1 downto 0 do
        begin
          check:=readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count);
          if check and (count=4) then
            realaddress2:=realaddress+memrec[lastselected].pointers[j].offset
          else
            raise exception.Create('The pointer can''t be completly read');
        end;
        address:=realaddress2;

      end
      else if res=mryes then address:=memrec[lastselected].pointers[length(memrec[lastselected].pointers)-1].Address else exit;
    end;
  end;

  if memrec[lastselected].VarType=0 then SetReadWriteBreakpoint(address,1); //byte
  if memrec[lastselected].VarType=1 then SetReadWriteBreakpoint(address,2); //word
  if memrec[lastselected].VarType=2 then SetReadWriteBreakpoint(address,4); //dword
  if memrec[lastselected].VarType=3 then SetReadWriteBreakpoint(address,4); //single
  if memrec[lastselected].VarType=4 then SetReadWriteBreakpoint(address,8); //double
  if memrec[lastselected].VarType=5 then SetReadWriteBreakpoint(address,1+(memrec[lastselected].Bit+memrec[lastselected].bitlength) div 8); //bit(will be handled as a byte)
  if memrec[lastselected].VarType=6 then SetReadWriteBreakpoint(address,8); //8-bytes (qword)
  if memrec[lastselected].VarType=7 then SetReadWriteBreakpoint(address,memrec[lastselected].Bit); //length of the text
  if memrec[lastselected].VarType=8 then SetReadWriteBreakpoint(address,memrec[lastselected].Bit); //length of the array

end;

procedure TMainForm.OpenProcesslist1Click(Sender: TObject);
begin
  speedbutton1.Click;
end;

procedure TMainForm.CloseCheatEngine1Click(Sender: TObject);
begin
  close;
end;

procedure TMainForm.Showashexadecimal1Click(Sender: TObject);
var i: integer;
begin
  for i:=0 to numberofrecords-1 do
    if selected[i] then
      memrec[i].ShowAsHex:=not memrec[lastselected].ShowAsHex;
  updatelist;
end;

procedure TMainForm.OpenMemorybrowser1Click(Sender: TObject);
begin
  btnMemoryView.click;
end;


procedure TMainForm.cbFastScanClick(Sender: TObject);
var i: integer;
begin

  if cbfasterscan.Checked then
  begin
    //hyperscan does not support this type
    i:=vartype.Items.IndexOf('All (Byte to Double)');
    if i>=0 then
      vartype.Items.Delete(i);

    i:=vartype.Items.IndexOf('Custom');
    if i>=0 then
      vartype.Items.Delete(i);
  end
  else
  begin
    i:=vartype.Items.IndexOf('All (Byte to Double)');
    if i=-1 then //it isn't in the list (anymore)
      vartype.Items.add('All (Byte to Double)'); //add it back

    i:=vartype.Items.IndexOf('Custom');
    if i=-1 then
      vartype.Items.add('Custom');

  end;

  if (sender=cbspeedhack) then
  begin
    if GetSystemType<4 then
      raise exception.Create(strNeedNewerWindowsVersion);
  end;

  if cbfasterscan.Checked or cbSpeedhack.Checked then
  begin
    if cefuncproc.hypermode=nil then
    begin
      try
        cefuncproc.hypermode:=THypermode.create;
      except
        cefuncproc.hypermode:=nil;
      end;
    end;
  end
  else if cefuncproc.hypermode<>nil then
  begin
    freeandnil(cefuncproc.hypermode);
  end;

  label51.visible:=cbspeedhack.checked;
  edit1.visible:=cbspeedhack.checked;
  label52.visible:=cbspeedhack.checked;
  edit2.visible:=cbspeedhack.checked;
  btnSetSpeedhack.visible:=cbspeedhack.checked;

  if cefuncproc.hypermode=nil then
  begin
    cbFasterscan.checked:=false;
    if formsettings.cbOldSpeedhack.checked then
      cbSpeedhack.Checked:=false;
    exit;
  end else cefuncproc.hypermode.WaitFor;

  if cefuncproc.hypermode=nil then exit; //self destruct

  if formsettings.cbOldSpeedhack.checked then
  begin
    if (cefuncproc.hypermode.speedhackenabled) and (not cbspeedhack.checked) then cefuncproc.hypermode.DisableSpeedhack;

    if (cefuncproc.hypermode.hyperscanwindow<>0) and
       (cbSpeedhack.checked) and
       (sender=cbSpeedhack) then
    begin
      if sendmessage(cefuncproc.hypermode.hyperscanwindow,wm_user+4,0,0)=$11223344 then
      begin
        cbspeedhack.Enabled:=true;
        cbunrandomizer.Enabled:=true;
        label52.Enabled:=true;
        label51.Enabled:=true;
        edit2.Enabled:=true;
        edit1.Enabled:=true;
        btnsetspeedhack.Enabled:=true;
        cefuncproc.hypermode.speedhackenabled:=true;
        btnSetSpeedhack.Click;
      end;
    end;
  end;

end;

procedure TMainForm.rbAllMemoryClick(Sender: TObject);
begin
  FromAddress.text:='00000000';
  ToAddress.text:='FFFFFFFF';
end;

procedure TMainForm.cbPauseWhileScanningClick(Sender: TObject);
resourcestring
  strdontbother='Don''t even bother. Cheat Engine uses the main thread to receive messages when the scan is done, freeze it and CE will crash!';
  strneeddebugger='To use this option the debugger must be attached to the game';
begin
  if (cbPauseWhileScanning.checked) and (processid=getcurrentprocessid) then
  begin
    cbPauseWhileScanning.Checked:=false;
    messagedlg(strdontbother,mtError,[mbok],0);
  end;

  if (cbPauseWhileScanning.checked) and (not startdebuggerifneeded) then
  begin
    cbPauseWhileScanning.Checked:=false;
    messagedlg(strneeddebugger,mtInformation,[mbok],0);
  end;
end;

procedure TMainForm.btnSetSpeedhackClick(Sender: TObject);
resourcestring
  strfailuretosetspeed='Failure to set the speed';
  strIncorrectspeed='The speed value is incorrect';
  strCantSetSpeed='I can''t set this speed. (must be bigger than 0)';
  strHyperscanFailed='The hyperthread failed to respond with the right answer';

var x: dword;
    speedf: single;
    speed: dword absolute speedf;
    sleeptime: integer;
    speedtext: string;
    i: integer;
begin
  if formsettings.cbOldSpeedhack.checked=false then
  begin
    editSH2.text:=edit2.Text;
    btnSetSpeedhack2.click;
    exit;
  end;

  try
    speedtext:=edit2.Text;
    speedf:=strtofloat(speedtext);
  except
    try
      if pos(',',speedtext)<>0 then
      begin
        //replace the , with a .
        i:=pos(',',speedtext);
        while i<>0 do
        begin
          speedtext[i]:='.';
          i:=pos(',',speedtext);
        end;
      end
      else
      begin
        //replace the . with a ,
        i:=pos('.',speedtext);
        while i<>0 do
        begin
          speedtext[i]:=',';
          i:=pos('.',speedtext);
        end;
      end;

      speedf:=strtofloat(speedtext);
    except
      raise exception.Create(strincorrectspeed);
    end;
  end;

  sleeptime:=strtoint(edit1.text);

  if speedf<=0 then raise exception.Create(strcantsetspeed);
  if speedf*sleeptime<1 then
  begin
    try
      sleeptime:=trunc(roundto(1/speedf,-1));
      if sleeptime=0 then sleeptime:=1;

      edit1.Text:=IntToStr(sleeptime);
    except
      exception.Create(strfailuretosetspeed);
    end;
  end;

  x:=sendmessage(cefuncproc.hypermode.hyperscanwindow,wm_user+6,sleeptime,speed);

  if x<>12345 then raise exception.Create(strHyperscanfailed);
end;



procedure TMainform.disableHypermode;
var i: integer;
begin
  if cefuncproc.hypermode<>nil then
  begin
    cefuncproc.hypermode.WaitFor;
    if cefuncproc.hypermode.speedhackenabled then cefuncproc.hypermode.disablespeedhack;
    freeandnil(cefuncproc.hypermode);
  end;
end;

procedure TMainForm.enableHypermode;
resourcestring
  strHyperscanfailed='Hypermode didn''t respond';
  strhookfailed='I can''t set the hook required to get into the process. Check if there isn''t any anti-cheat protection running.';
var
  CEScanProcAddress:pointer;

  winhandle,possiblewinhandle: thandle;
  winprocess: dword;
  winthreadid: dword;

  x: ^byte;
  i,j: integer;
  s: string;
begin
  if cefuncproc.hypermode<>nil then exit;
  cefuncproc.hypermode:=thypermode.create;
end;

procedure TMainForm.Description1Click(Sender: TObject);
begin
  description[lastselected-scrollbar1.position].OnDblClick(value[lastselected-scrollbar1.position]);
end;

procedure TMainForm.Address1Click(Sender: TObject);
begin
  address[lastselected-scrollbar1.position].OnDblClick(value[lastselected-scrollbar1.position]);
end;

procedure TMainForm.ype1Click(Sender: TObject);
begin
  valtype[lastselected-scrollbar1.position].OnDblClick(value[lastselected-scrollbar1.position])
end;

procedure TMainForm.Value1Click(Sender: TObject);
begin
  value[lastselected-scrollbar1.position].OnDblClick(value[lastselected-scrollbar1.position])
end;

procedure TMainForm.ProcessLabelDblClick(Sender: TObject);
var peprocesS: dword;
    needed:dword;
    x: dword;
    processInfo:TProcessBasicInformation;

    buf:pchar;
begin
  if formsettings.cbKernelOpenProcess.Checked then
  begin
    if processid=0 then exit;
    
    if not IsValidHandle(processhandle) then
      if messagedlg('The process isn''t fully opened. Indicating a invalid ProcessID. You still want to find out the EPROCESS? (BSOD is possible)',mtwarning,[mbyes,mbno],0)<>mryes then exit;

    peprocess:=GetPEProcess(processid);
    showmessage('PEProcess='+IntToHex(peprocess,8));
    memorybrowser.memoryaddress:=peprocess;

  end;
end;

procedure TMainForm.ProcessLabelMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if (button = mbright) and (darkbytekernel<>0) and IsValidHandle(processhandle) then
    tfrmProcessInfo.Create(self).Show;
end;

procedure TMainForm.cbUnrandomizerClick(Sender: TObject);
begin
  if cbunrandomizer.checked then
  begin
    if(messagedlg('This will scan for and change some routines that are commonly used to'+' generate a random value so they always return the same. Please be aware that there is a chance it overwrites the wrong routines causing the program to crash, or that the program uses an unknown random generator. Continue?',mtwarning,[mbyes,mbno],0)=mryes) then
    begin
      unrandomize:=tunrandomize.create(true);
      with unrandomize do
      begin

        progressbar:=tprogressbar.create(self);
        progressbar.left:=twincontrol(sender).Left;
        progressbar.top:=twincontrol(sender).top;
        progressbar.Width:=twincontrol(sender).width;
        progressbar.height:=twincontrol(sender).height;

        progressbar.parent:=self;
        cbunrandomizer.enabled:=false;
        resume;
      end;
    end else cbUnrandomizer.Checked:=false;
  end
  else
  begin
    if unrandomize<>nil then
      freeandnil(unrandomize);
  end;
end;

procedure TMainForm.cbUnrandomizerMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if cbunrandomizer.Checked and (button=mbright) then
  begin
    //show unrandimized addresses
    unrandomize.showaddresses;
  end;
end;

procedure TMainForm.disableautoassemblecheat(i: integer);
var code: tstringlist;
begin
  code:=tstringlist.Create;
  code.Text:=memrec[i].autoassemblescript;
  try
    memrec[i].Frozen:=not autoassemble(code,false,false,false,false,memrec[i].allocs);
    if memrec[i].Frozen then //failed, lets say if reloading the symbols can help
    begin
      symhandler.reinitialize;
      memrec[i].Frozen:=not autoassemble(code,false,false,false,false,memrec[i].allocs);
    end;
  except

  end;

  code.free;
end;

procedure TMainForm.enableautoassemblecheat(i: integer);
var code: tstringlist;
begin
  code:=tstringlist.Create;
  code.Text:=memrec[i].autoassemblescript;
  try
    setlength(memrec[i].allocs,1);
    memrec[i].Frozen:=autoassemble(code,false,true,false,false,memrec[i].allocs);

    if not memrec[i].frozen then
    begin
      symhandler.reinitialize;
      memrec[i].Frozen:=autoassemble(code,false,true,false,false,memrec[i].allocs);
    end;

  except

  end;

  code.free;
end;


procedure TMainForm.addaddress(description: string; address:dword; const offsets: array of dword; offsetcount: integer; ispointer: boolean; vartype: integer; length: integer; startbit:integer; unicode,showashex: boolean);
var i: integer;
begin
  if offsetcount=0 then ispointer:=false; //safeguard

  inc(NumberOfRecords);
  reserveMem;

  memrec[numberofrecords-1].Description:=description;
  memrec[numberofrecords-1].Address:=address;
  memrec[NumberOfRecords-1].VarType:=vartype;
  memrec[numberofrecords-1].unicode:=unicode;
  memrec[numberofrecords-1].IsPointer:=ispointer;
  memrec[numberofrecords-1].Bit:=startbit; //startbit is also used for size for strings
  memrec[numberofrecords-1].bitlength:=length;
  memrec[numberofrecords-1].showashex:=showashex;

  if ispointer then
  begin
    setlength(memrec[numberofrecords-1].pointers,offsetcount);

    for i:=0 to offsetcount-1 do
    begin
      memrec[numberofrecords-1].pointers[i].Address:=address;
      memrec[numberofrecords-1].pointers[i].offset:=offsets[i];
    end;
  end;

  memrec[NumberOfRecords-1].Frozen:=false;
  memrec[NumberOfRecords-1].FrozenValue:=0;
  FrozenFvalue[NumberOfRecords-1]:=0;
  FrozenStrings[NumberOfRecords-1]:='';
  Hotkeystrings[NumberOfRecords-1]:='';
  Hotkeys[NumberOfRecords-1]:=-1;

  UpdateScreen;
  updatelist;

end;

procedure TMainForm.addaddress(description: string; address:dword; const offsets: array of dword; offsetcount: integer; ispointer: boolean; vartype: integer; length: integer; startbit:integer; unicode: boolean);
begin
  addaddress(description,address,offsets,offsetcount,ispointer,vartype,length,startbit,unicode,false);
end;

procedure TMainForm.Foundlist3CustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
  if foundlist.inmodule(item.index) then foundlist3.Canvas.Font.Color:=clgreen;
end;

procedure TMainForm.actOpenExecute(Sender: TObject);
var merge: boolean;
    app: word;
    Extension: string;
resourcestring
  strUnknownExtension='Unknown extension';
begin
  if editingscript then raise exception.create('First close your script edit window before opening a new table');

  merge:=false;
  if not autoopen then
    if CheckIfSaved=false then exit;

  OpenDialog1.InitialDir:=cheatenginedir;

  if autoopen or Opendialog1.Execute then
  begin
    autoopen:=false;
    Extension:=uppercase(extractfileext(opendialog1.filename));
    if (Extension<>'.XML') and
       (Extension<>'.PTR') and
       (Extension<>'.AMT') and
       (Extension<>'.GH') and
       (Extension<>'.CET') and
       (Extension<>'.CT2') and
       (Extension<>'.CT3') and
       (Extension<>'.CT') and
       (Extension<>'.EXE') then raise exception.create(strUnknownExtension);


    if ((numberofrecords>0) or (advancedoptions.numberofcodes>0)) and (Extension<>'.EXE') then app:=messagedlg('You wish to merge the current table with this table?',mtConfirmation,mbYesNoCancel,0);
    case app of
      mrCancel: exit;
      mrYes: merge:=true;
      mrNo: merge:=false;
    end;

    LoadTable(Opendialog1.filename,merge);
    reinterpretaddresses;

  end;

  if advancedoptions.codelist2.items.Count>0 then
  begin
    advancedoptions.Position:=podesigned;
    advancedoptions.Left:=mainform.left-advancedoptions.Width;
    advancedoptions.Top:=mainform.Top+mainform.Height-advancedoptions.Height;

    if (advancedoptions.Left<0) or (advancedoptions.Top+advancedoptions.Height>screen.height) then
    begin
      advancedoptions.left:=0;
      advancedoptions.Top:=screen.Height-advancedoptions.Height;

    end;
    advancedoptions.show;
  end;

  Updatescreen;
  updatelist;
end;

procedure TMainForm.actSaveExecute(Sender: TObject);
begin
  if (savedialog1.FileName='') and (opendialog1.filename<>'') then
  begin
    //set the filename the table was opened with to the filename you save as default to
    //and dont forget to change the extension to .CT
    savedialog1.FileName:=ChangeFileExt(opendialog1.FileName,'');
  end;

  SaveDialog1.InitialDir:=cheatenginedir;
  if Savedialog1.Execute then
    savetable(savedialog1.FileName);


end;

procedure TMainForm.actAutoAssembleExecute(Sender: TObject);
begin
  tfrmautoinject.create(self).show;
end;

procedure TMainform.changeScriptCallback(script: string; changed: boolean);
{
Gets called when a edit script is done
}
begin
  if editingscript then
  begin
    editingscript:=false;
    if changed then
    begin
      memrec[editedscript].autoassemblescript:=script;
      itemshavechanged:=true;
    end;
    
  end else raise exception.Create('Unexpected scriptchange');
end;

procedure TMainForm.Changescript1Click(Sender: TObject);
var x: TFrmAutoInject;
    y: array of integer;
begin
  if editingscript then raise exception.Create('First finish editing the other script');

  if lastselected<>-1 then
  begin
    x:=tfrmautoinject.Create(self);
    with x do
    begin
      name:='AAEditScript';

      new1.Enabled:=false;

      editscript:=true;
      editscript2:=true;
      callbackroutine:=changeScriptCallback;

      mainform.editingscript:=true;
      mainform.editedscript:=lastselected;


      assemblescreen.Text:=memrec[lastselected].autoassemblescript;

      {
      if showmodal=mrok then
      begin
        if assemblescreen.text<>memrec[lastselected].autoassemblescript then
          editedsincelastsave:=true;
          
        memrec[lastselected].autoassemblescript:=assemblescreen.text;
        free; //needed for editscript
      end; }

      formstyle:=fsStayOnTop;

      loadformposition(x,y);
      show;

    end;
  end;

end;

procedure TMainForm.Forcerechecksymbols1Click(Sender: TObject);
begin
  symhandler.reinitialize;
  symhandler.waitforsymbolsloaded;
  reinterpretaddresses;
  updatescreen;
end;

procedure TMainForm.Label5Click(Sender: TObject);
begin
{  SetProcessAffinityMask(getcurrentprocess,1);
  sleep(500);
  dbktest;
  SetProcessAffinityMask(getcurrentprocess,2);
  sleep(500);
  dbktest;
  SetProcessAffinityMask(getcurrentprocess,3);
                                                 }
end;

procedure TMainform.edit;
var frmPasteTableentry: TfrmPasteTableentry;
    replace_find: string;
    replace_with: string;
    changeoffsetstring: string;
    changeoffset,x: dword;
    i,j: integer;
    hasselected: boolean;
begin
  if NumberOfRecords=0 then exit;
  
  frmPasteTableentry:=TfrmPasteTableentry.create(self);
  try
    frmPasteTableentry.caption:='Edit addresses';
    frmPasteTableentry.Button1.Caption:='Edit';

    if frmpastetableentry.showmodal=mrcancel then exit;
    replace_find:=frmpastetableentry.edtFind.text;
    replace_with:=frmpastetableentry.edtReplace.text;

    changeoffsetstring:='$'+stringreplace(frmpastetableentry.edtOffset.Text,'-','-$',[rfReplaceAll]);
    changeoffsetstring:=stringreplace(changeoffsetstring,'$-','-',[rfReplaceAll]);

    try
      changeoffset:=strtoint(changeoffsetstring);
    except
      changeoffset:=0;
    end;
  finally
    frmPasteTableentry.free;
  end;


  hasselected:=false;
  for i:=0 to numberofrecords-1 do
  begin
    if Selected[i] then
    begin
      hasselected:=true;
      break;
    end;
  end;

  for i:=0 to numberofrecords-1 do
  begin
    if (hasselected and selected[i]) or (not hasselected) then
    begin
      memrec[i].Description:=StringReplace(memrec[i].Description,replace_find,replace_with,[rfReplaceAll,rfIgnoreCase]);
      memrec[i].Address:=memrec[i].Address+changeoffset;

      if memrec[i].interpretableaddress<>'' then
      begin
        try
          x:=symhandler.getAddressFromName(memrec[i].interpretableaddress);
          x:=x+changeoffset;
          memrec[i].interpretableaddress:=symhandler.getNameFromAddress(x,true,true)
        except
          memrec[i].interpretableaddress:=inttohex(memrec[i].Address,8);
        end;
      end;




      for j:=0 to length(memrec[i].pointers)-1 do
      begin
        //address
        memrec[i].pointers[j].Address:=memrec[i].pointers[j].Address+changeoffset;

        if memrec[i].pointers[j].interpretableaddress<>'' then
        begin
          try
            x:=symhandler.getAddressFromName(memrec[i].pointers[j].interpretableaddress);
            x:=x+changeoffset;
            memrec[i].pointers[j].interpretableaddress:=symhandler.getNameFromAddress(x,true,true)
          except
            memrec[i].pointers[j].interpretableaddress:=inttohex(memrec[i].Address,8);
          end;
        end;
      end;
    end;
  end;

  updatescreen;
  Updatelist;
end;

procedure TMainForm.Smarteditaddresses1Click(Sender: TObject);
begin
  edit;
end;

procedure TMainForm.Pointerscanforthisaddress1Click(Sender: TObject);
var res: integer;
    realaddress2,realaddress,address,count: dword;
    j: integer;
    check: boolean;
    i: integer;
    findpointeroffsets: boolean;

    frmPointerScanner: TfrmPointerScanner;
begin
  findpointeroffsets:=false;
  try
    if memrec[lastselected].IsPointer then
    begin
      if MessageDlg('This is already a pointer. Do you want to find another pointer that fits with these offsets?',mtInformation, [mbyes,mbno], 0)=mryes then
        findpointeroffsets:=true;

      realaddress2:=memrec[lastselected].pointers[length(memrec[lastselected].pointers)-1].Address;
      for j:=length(memrec[lastselected].pointers)-1 downto 0 do
      begin
        check:=readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count);
        if check and (count=4) then
          realaddress2:=realaddress+memrec[lastselected].pointers[j].offset
        else
          raise exception.Create('The pointer can''t be completly read');
      end;
      address:=realaddress2;
    end
    else
      address:=memrec[lastselected].address;
  except
    address:=memrec[lastselected].address;
  end;


  res:=mryes;
 // with tfrmInjectedpointerscanornot.create(self) do
//  begin
//    res:=showmodal;
//    free;
//  end;

  if res=mrcancel then exit;

  if res=mryes then
  begin
    //default
    frmPointerScanner:=tfrmpointerscanner.create(self);
    frmPointerScanner.show;

    if frmpointerscannersettings=nil then
      frmpointerscannersettings:=tfrmpointerscannersettings.create(self);

    frmpointerscannersettings.edtAddress.text:=inttohex(address,8);

    if findpointeroffsets then
    begin
      //create and fill in the offset list
      frmpointerscannersettings.cbMustEndWithSpecificOffset.checked:=true;
      TOffsetEntry(frmpointerscannersettings.offsetlist[0]).offset:=memrec[lastselected].pointers[0].offset;

      for i:=1 to length(memrec[lastselected].pointers)-1 do
      begin
        frmpointerscannersettings.btnAddOffset.Click;
        TOffsetEntry(frmpointerscannersettings.offsetlist[i]).offset:=memrec[lastselected].pointers[i].offset;
      end;
    end;

    frmPointerScanner.Method3Fastspeedandaveragememoryusage1.Click;
  end
  else if res=mrno then
  begin
    //injected scan
    injectpointerscan(address);
  end;
end;

procedure testx(arg1:pointer; arg2:pointer; arg3:pointer); stdcall;
begin
asm
  pushad
  pushad
  popad
  popad
end;

end;

procedure TMainForm.Label53Click(Sender: TObject);
var x: integer;
begin
  asm
    mov ax,$40
    mov es,ax

  end;
  showmessage(inttohex(x,8));
end;

procedure TMainForm.pointerscanner_addaddress(var Message: TMessage);
var p: thandle;
    sourcebuffer: pointer;
    ms: tmemorystream;
    x: dword;
    address: dword;
    offsets: array of cardinal;
    i: integer;

    cds: PCOPYDATASTRUCT;
    st: pchar;
    s: string;
begin
  cds:=pointeR(message.LParam);
  if cds=nil then exit;

  try
    if cds.dwData=$ce then
    begin
      ms:=tmemorystream.Create;
      try
        getmem(sourcebuffer,cds.cbData);
        copymemory(sourcebuffer,cds.lpData,cds.cbData);

        ms.writebuffer(sourcebuffer^,cds.cbData);
        freemem(sourcebuffer);

        ms.Position:=0;
        ms.ReadBuffer(x,sizeof(x));
        getmem(st,x+1);
        ms.readbuffer(st^,x);
        st[x]:=#0;
        s:=st;
        freemem(st);

        address:=symhandler.getAddressFromName(s);

        setlength(offsets,0);

        while ms.Position<ms.Size do
        begin
          ms.ReadBuffer(x,4);
          setlength(offsets,length(offsets)+1);
          offsets[length(offsets)-1]:=x;
        end;

        addaddress('Pointerscan address',address,offsets,length(offsets),length(offsets)>0,2,0,0,false,false);
        if memrec[numberofrecords-1].IsPointer then //yes, but check anyhow
        begin
          memrec[numberofrecords-1].pointers[length(memrec[numberofrecords-1].pointers)-1].Interpretableaddress:=s;
        end;
      finally
        ms.Free;
      end;

    end;
  except

  end;
end;

procedure TMainForm.Label57Click(Sender: TObject);
{var i: dword;   }
begin
 { i:=newkernelhandler.dbvm_version;
  showmessage('dbvm version='+inttohex(i,8));  }
end;

procedure TMainform.OnToolsClick(sender: TObject);
begin
  shellexecute(0,'open',pchar(formsettings.lvTools.Items[TMenuItem(sender).Tag].SubItems[0]),'','',SW_SHOW);
end;

Procedure TMainForm.plugintype5click(sender:tobject);
var x: TPluginfunctionType5;
begin
  x:=TPluginfunctionType5(tmenuitem(sender).Tag);
  if x<>nil then
    x.callback();
end;

Procedure TMainForm.plugintype0click(sender:tobject);
var selectedrecord: PPlugin0_SelectedRecord;
var x: TPluginfunctionType0;
    interpretableaddress: string[255];
    description: string[255];
    i: integer;
    offsets: PDwordArray;

    a,b,c,d,e,f,g,h,j: dword;
begin


  interpretableaddress:=' ';
  description:=' ';

  if (lastselected<>-1) and (lastselected<numberofrecords) and (selected[lastselected]) then
  begin
    getmem(selectedrecord,sizeof(TPlugin0_SelectedRecord));
    //fill it with data

    if memrec[lastselected].IsPointer then
      interpretableaddress:=memrec[lastselected].pointers[length(memrec[lastselected].pointers)-1].Interpretableaddress
    else
      interpretableaddress:=memrec[lastselected].interpretableaddress;

    selectedrecord.interpretedaddress:=@interpretableaddress[1];

    selectedrecord.address:=memrec[lastselected].Address;
    selectedrecord.ispointer:=memrec[lastselected].IsPointer;
    selectedrecord.countoffsets:=length(memrec[lastselected].pointers);

    getmem(offsets,selectedrecord.countoffsets*4); //don't forget to free
    selectedrecord.offsets:=offsets;
    for i:=0 to selectedrecord.countoffsets-1 do
      selectedrecord.offsets[i]:=memrec[lastselected].pointers[i].offset;

    description:=memrec[lastselected].Description;
    selectedrecord.description:=@description[1];

    selectedrecord.valuetype:=memrec[lastselected].VarType;
    selectedrecord.size:=memrec[lastselected].bit;    
  end
  else
    selectedrecord:=nil;

  x:=TPluginfunctionType0(tmenuitem(sender).Tag);
  if x<>nil then
  begin

    interpretableaddress[length(interpretableaddress)+1]:=#0;
    description[length(description)+1]:=#0;

    if x.callback(selectedrecord) then
    begin
      if selectedrecord<>nil then
      begin
        interpretableaddress[255]:=#0;
        description[255]:=#0;

        pbyte(@interpretableaddress[0])^:=StrLen(@interpretableaddress[1]);
        pbyte(@description[0])^:=StrLen(@description[1]);

        if memrec[lastselected].IsPointer then
          memrec[lastselected].pointers[length(memrec[lastselected].pointers)-1].Interpretableaddress:=interpretableaddress
        else
          memrec[lastselected].interpretableaddress:=interpretableaddress;

        memrec[lastselected].Description:=description;
        memrec[lastselected].VarType:=selectedrecord.valuetype;

        //load back and free memory
        freemem(offsets); //using my own var instead the user is lame enough to mess up the pointer
        reinterpretaddresses;
      end;
    end;
    //showmessage(inttohex(dword(@x.callback),8));
  end;
end;


//------------------foundlist------------------

procedure TMainForm.Foundlist3Data(Sender: TObject; Item: TListItem);
var extra: dword;
    value: string;
    address: string;
    valuetype: TVariableType;
begin
  //put in data
  try
    address:=inttohex(foundlist.GetAddress(item.Index,extra,value),8);

    if foundlist.vartype = 5 then //binary
    begin
      address:=address+'^'+inttostr(extra);
    end
    else
    if foundlist.vartype = 9 then //all
    begin
      valuetype:=TVariableType(extra);
      
      //here valuetype is stored using the new method
      case valuetype of
        vtByte: address:=address+':1';
        vtWord: address:=address+':2';
        vtDword: address:=address+':4';
        vtQword: address:=address+':8';
        vtSingle: address:=address+':s';
        vtDouble: address:=address+':d';
      end;
    end
    else //normal
      address:=inttohex(foundlist.GetAddress(item.Index,extra,value),8);

    item.Caption:=address;
    item.subitems.add(value);
  except
    showmessage(inttostr(item.index));
  end;
end;

procedure TMainForm.UpdateFoundlisttimerTimer(Sender: TObject);
begin
  foundlist.RefetchValueList;
end;

procedure TMainForm.Foundlist3KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if ((key=ord('A')) and (ssctrl in Shift) and not (ssalt in Shift)) then
  begin
    //select all
    if foundlist3.Items.Count<5000 then
      foundlist3.SelectAll;

  end;
end;

procedure TMainForm.mode16Click(Sender: TObject);
begin
{  disassembler.mode16:=mode16.checked; }
end;

var raaa: packed record
  eip: dword;
  segment: word;  
end;

var
  c: tcontext;
procedure TMainForm.Label59Click(Sender: TObject);
begin

end;

{
var usedkernelbase: dword=0;
    usedkernelstring: string;
function FindUsedKernel: string;
//Will return the string of the currently used kernelfile
var need: dword;
    x: PPointerArray;
    count: integer;
    drivername: pchar;
    i: integer;
begin

  if usedkernelbase=0 then
  begin
    EnumDevicedrivers(nil,0,need);
    getmem(x,need);
    try
      if enumDevicedrivers(@x[0],need,need) then
      begin
        count:=need div 8;
        getmem(drivername,200);

        try
          for i:=0 to count-1 do
          begin
            GetDevicedriverBaseName(x[i],drivername,200);
            if usedkernelbase=0 then //not found so keep looking
            begin
              if pos('krnl',drivername)>0 then  //first one to encounter is it. (and can't pick the first one sicne thats ntdll.dll)
              begin
                usedkernelbase:=dword(x[i]);
                usedkernelstring:=drivername;
                result:=drivername;
                break;
              end;
            end;

            
          end;
        finally
          freemem(drivername);
        end;
      end;
    finally
      freemem(x);
    end;
  end
  else result:=usedkernelstring;
end;

}
{
type Ttestfunc=function(a: dword): boolean; stdcall;
   }
function x(a: dword):BOOL; stdcall;
begin
  result:=(a<100);
end;
     {
var v1: real48;
    v2: Single;
    v3: double;
    v4: Extended;
    v5: Comp;
    v6: Currency;
                     }

var xxxb: integer;

procedure xxxa; stdcall;
asm
  pushad
  mov [xxxb],eax
  popad
end;

procedure ChangeIcon(hModule: HModule; restype: pchar; resname: pchar; lparam: thandle); stdcall;
var
  iconRSRC: HRSRC;
  iconG: HGLOBAL;
  resSize: integer;
  p: pointer;
begin
  iconRSRC:=FindResource(hModule,resName,resType);
  resSize:=SizeofResource(hModule,iconRSRC);
  iconG:=LoadResource(hModule,iconRSRC);
  p:=LockResource(iconG);

//  nvoke UpdateResource,hUpdate,lpszType,lpszName,ecx,pData,nSizeOfRes
//;invoke FreeResource,hResLoaded
//mov eax,TRUE

  UpdateResource(lParam,restype, resName, 1030,p,resSize);

end;


var    abc: TReversePointerListHandler;

procedure TMainForm.Browsethismemoryregioninthedisassembler1Click(
  Sender: TObject);
var a,b: dword;
    s: string;
begin
  if (foundlist3.ItemIndex<>-1) then
  begin
    memorybrowser.disassemblerview.SelectedAddress:=foundlist.GetAddress(foundlist3.itemindex,b,s);
    memorybrowser.show;
  end;
end;

procedure TMainform.autoattachcheck;
var pl: TStringlist;
    i,j,k: integer;
    newPID: dword;
    pli: PProcessListInfo;
begin
  //in case there is no processwatcher this timer will be used to enumare the processlist every 2 seconds
  if (not formsettings.cbAlwaysAutoAttach.checked) and ((processhandle<>0) or (processid<>0)) then
    exit;

  pl:=tstringlist.Create;
  getprocesslist(pl);

  try

    for i:=0 to autoattachlist.Count-1 do
    begin
      for j:=0 to pl.Count-1 do //can't do indexof
      begin
        if pos(uppercase(autoattachlist.Strings[i]),uppercase(pl.strings[j]))=10 then
        begin
          //the process is found

          val('$'+pl.strings[j],newPID,k);
          if processid=newPID then exit; //already attached to this one

          ProcessHandler.processid:=newPID;
          unpause;
          DetachIfPossible;

          MainForm.ProcessLabel.caption:=pl.strings[j];
          Open_Process;
          enablegui(false);

          openProcessEpilogue('',0,0,true);

          symhandler.reinitialize;
          reinterpretaddresses;
        end;
      end;

    end;
  //  pl.IndexOf(autoattachlist.items[i]);

  finally
    for i:=0 to pl.count-1 do
      if pl.Objects[i]<>nil then
      begin
        pli:=pointer(pl.Objects[i]);
        if pli.processIcon>0 then
          DestroyIcon(pli.processIcon);
        freemem(pli);
      end;

    pl.free;
  end;
end;

procedure TMainForm.AutoAttachTimerTimer(Sender: TObject);
begin
  autoattachcheck;
end;



procedure TMainForm.Button2Click(Sender: TObject);
var svalue2: string;
  percentage: boolean;
begin
  foundlist.Deinitialize; //unlock file handles


  if cbpercentage<>nil then
    percentage:=cbpercentage.checked
  else
    percentage:=false;

  if button2.tag=0 then
  begin
    progressbar1.min:=0;
    progressbar1.max:=1000;
    progressbar1.position:=0;

    if scanvalue2<>nil then
      svalue2:=scanvalue2.Text
    else
      svalue2:='';

    lastscantype:=scantype.ItemIndex; 

    if cbPauseWhileScanning.checked then
    begin
      advancedoptions.Pausebutton.down:=true;
      advancedoptions.Pausebutton.Click;
    end;


    memscan.firstscan(GetScanType2, getVarType2, roundingtype, scanvalue.text, svalue2, scanStart, scanStop, fastscan, scanreadonly, HexadecimalCheckbox.checked, rbdec.checked, cbunicode.checked, cbCaseSensitive.checked, percentage, SelectedCustomScanData, SelectedCustomScanType);
    DisableGui;
    SpawnCancelButton;
  end
  else if button2.tag=2 then
  begin
    //newscan
    button2.Tag:=0;
    donewscan;
    memscan.newscan; //cleanup memory and terminate all background threads
  end;
end;

procedure TMainForm.ScanDone(var message: TMessage);
var i: integer;
    canceled: boolean;
begin
  i:=0;
  canceled:=false;

  button2.Tag:=2;
  button2.Caption:='Scan';
  button4.tag:=0;
  progressbar1.Position:=0;

  SetProgressState(tbpsNone);


  foundcount:=memscan.GetFoundCount;


  if message.wparam>0 then
  begin
    messagedlg('Scan error:'+memscan.GetErrorString, mtError,[mbok],0);
  end;       

{  else}
//  showmessage('SCAN SUCCES. time='+inttostr(after-before));


  enablegui(memscan.LastScanType=stNextScan);
  destroyCancelButton;


  foundlist.Initialize(getvartype,i,hexadecimalcheckbox.checked,formsettings.cbShowAsSigned.Checked,formsettings.cbBinariesAsDecimal.Checked,cbunicode.checked);


  if memscan.lastscantype=stFirstScan then
  begin
    //firstscan Epilogue
    Groupbox1.Enabled:=false;
    for i:=0 to groupbox1.ControlCount-1 do
      groupbox1.Controls[i].Enabled:=false;

    vartype.Enabled:=false;
    nextscanbutton.enabled:=true;
    newscan.Caption:=strNewScan;
  end;

  beep; //let the blind user know the scan has finished (See, I'm thinking about the visually impeared users...)

  progressbar1.Position:=0;
  UpdateFoundlisttimer.Enabled:=true;
  
  Scantype.ItemIndex:=lastscantype;
  UpdateScanType;

  scanepilogue(canceled);
end;

procedure Tmainform.CancelbuttonClick(sender: TObject);
begin
  if cancelbutton.tag=0 then
  begin
    cancelbutton.Caption:='Terminating scan...';
    cancelbutton.Enabled:=false;
    cancelbutton.Tag:=1; //force termination
    cancelbutton.Hint:='This button will force cancel a scan. Expect memory leaks';
    cancelbutton.ParentShowHint:=false;
    cancelbutton.ShowHint:=true;
    memscan.terminatescan(false);

    cancelbuttonenabler.Enabled:=false;
    cancelbuttonenabler.interval:=8000; //8 seconds
    cancelbuttonenabler.tag:=1;
    cancelbuttonenabler.enabled:=true;
  end
  else
  begin
    //force it. It took too long
    memscan.TerminateScan(true);
  end;
end;

procedure Tmainform.CancelbuttonenablerInterval(sender: TObject);
begin
  if cancelbutton<>nil then cancelbutton.enabled:=true;

  if cancelbutton.Tag=1 then
    cancelbutton.Caption:='Force termination';
  TTimer(sender).Enabled:=false;
end;

procedure TMainForm.Button4Click(Sender: TObject);
var svalue2: string;
    estimateddiskspaceneeded: Uint64;
    diskspacefree, totaldiskspace: int64;
    totaldiskspacefree: LARGE_INTEGER;
    percentage: boolean;
begin
  if cbpercentage<>nil then
    percentage:=cbpercentage.checked
  else
    percentage:=false;

  estimateddiskspaceneeded:=foundcount*8*3;
  GetDiskFreeSpaceEx(pchar(cheatenginedir), diskspacefree, totaldiskspace,@totaldiskspacefree);

  if estimateddiskspaceneeded>diskspacefree then
    if MessageDlg('You are low on diskspace on the folder where the scanresults are stored. Scanning might fail. Are you sure you want to continue?',mtwarning,[mbyes,mbno],0)<>mryes then exit;

  foundlist.Deinitialize; //unlock file handles

  if cbPauseWhileScanning.checked then
  begin
    advancedoptions.Pausebutton.down:=true;
    advancedoptions.Pausebutton.Click;
  end;

  progressbar1.min:=0;
  progressbar1.max:=1000;
  progressbar1.position:=0;

  
  if scanvalue2<>nil then
    svalue2:=scanvalue2.Text
  else
    svalue2:='';

  lastscantype:=scantype.ItemIndex;

  memscan.nextscan(GetScanType2, roundingtype, scanvalue.text, svalue2, scanStart, scanStop, fastscan, scanreadonly, HexadecimalCheckbox.checked, rbdec.checked, cbunicode.checked, cbCaseSensitive.checked, percentage, SelectedCustomScanData, SelectedCustomScanType);
  DisableGui;
  SpawnCancelButton;
end;

procedure TMainform.scanepilogue(canceled: boolean);
var vtype: integer;
    i: integer;
    bytes: tbytes;
begin
  vtype:=getvartype;
  if not canceled then
  begin
    case vtype of
      5: i:=memscan.getbinarysize;
      7: i:=length(scanvalue.Text);
      8: //array of byte
      begin
        setlength(bytes,0);
        try
          ConvertStringToBytes(scanvalue.Text,hexadecimalcheckbox.checked,bytes );
          i:=length(bytes);
        except
          i:=1;
        end;
        setlength(bytes,0);
      end;

      10: i:=memscan.Getcustomvariablesize;
    end;
    foundlist.Initialize(vtype,i,hexadecimalcheckbox.checked,formsettings.cbShowAsSigned.Checked,formsettings.cbBinariesAsDecimal.Checked,cbunicode.checked);
  end
  else foundlist.Initialize(vtype); //failed scan, just reopen the addressfile

  try
    if scanvalue.Visible and scanvalue.Enabled then
    begin
      scanvalue.SetFocus;
      scanvalue.SelectAll;
    end
    else
    if not canceled then
    begin
      NextScanButton.SetFocus;
    end;
  except

  end;



  if cbPauseWhileScanning.checked then
  begin
    advancedoptions.Pausebutton.down:=false; //resume
    advancedoptions.Pausebutton.Click;
  end;

end;

//-----------------custom scan-----------------//
resourcestring strCustomScanConfig='Custom scan config';
procedure TMainform.EditCustomScanButtonClick(sender: TObject);
var autoinjectform: TFrmAutoInject;
    scandata: tstringlist;
    scriptname: string;
begin
  scandata:=SelectedCustomScanData;
  if scandata=nil then exit;

  autoinjectform:=TFrmAutoInject.Create(self);
  try
    with autoinjectform do
    begin
      caption:=caption+' '+strCustomScanConfig;

      assemblescreen.Text:=scandata.text;
      new1.Enabled:=false;

      editscript:=true;
      injectintomyself:=true;      

      if showmodal=mrok then
      begin
        scriptname:=customscanscripts[scantype.itemindex].name;
        if not inputquery(strCustomScanConfig,'The script seems to be valid. What is the name of this script?',scriptname) then exit;

        scandata.Text:=assemblescreen.Text;
        customscanscripts[scantype.itemindex].name:=scriptname;
      end;
      

    end;
  finally
    autoinjectform.free;
  end;
end;

procedure TMainform.CreateCustomScanButtonClick(sender: TObject);
{
Open a autoassembler window and fill it in.
Give hints that people can use loadlibratry and functions from dll's
}

var scriptname: string;
    i: integer;
begin

  with tfrmautoinject.Create(self) do
  begin
    try
      caption:=caption+' '+strCustomScanConfig;
      with assemblescreen.lines do
      begin
        add('[enable]');
        add('{do not change the allocnames of the following code, you are free to add new allocs though');
        add('of course then don''t forget to dealloc them at [disable] as well}');
        add('alloc(checkroutine,2048)');
        add('alloc(prologue,2048)');
        add('alloc(epilogue,2048)');
        add('alloc(fastscanstepsize,4)');
        add('alloc(variablesize,4)');
        add('alloc(firstscan,4)');
        add('alloc(scantext,4) //will get the pointer to the given string');
        add('alloc(scanvalue,8) //will get the value of the input string converted to an 8-byte value');
        add('alloc(singlescanvalue,4) //will get the float type of the input');
        add('alloc(doublescanvalue,8) //will get the double type of the input');
        add('');
        add('variablesize:');
        add('dd 4 //defines how many bytes get saved for each found result');
        add('');
        add('fastscanstepsize:');
        add('dd 1 //defines the stepsize when using fastscan (1=no difference)');
        add('');
        add('firstscan:');
        add('dd 0 //set to 1 if you want the old value to be that of the first scan');

        add('');
        add('/* routines: ');
        add('Hint: You can write these routines in any language you like and export them as dll''s. ');
        add('Then use loadlibraty and call exportfunction to use them*/');
        add('');
        add('checkroutine:');
        add('/*');
        add('edx=pointer to new value');
        add('ecx=pointer to old value');
        add('*/');
        add('');
        add('//example of 4-byte "exact value" scan for the value 100:');
        add('mov eax,[edx]  //eax gets the new value');
        add('cmp eax,#100  //compare eax with #100, # tells the assembler to read it as a decimal instead of hex');
        add('setz al //sets al to 1 if match, 0 if false (upper bits of eax are ignored)');
        add('ret');
        add('');

        add('prologue:');
        add('//You can put some code here that gets executed BEFORE the scan starts');
        add('ret');
        add('');
        add('epilogue:');
        add('//You can put some code here that gets executed AFTER the scan finishes');
        add('ret');
        add('');
        add('scandisplayroutinetype:');
        add('/*');
        add('displayroutinetype is a ''special'' globally registered symbol (No need to alloc)');
        add('The byte at this address specifies how the values are shown');
        add('0=1 byte notation');
        add('1=2 byte notation');
        add('2=4 byte notation');
        add('3=8 byte notation');
        add('4=float notation');
        add('5=double notation');
        add('6=array of bytes');
        add('7=string ascii');
        add('8=string unicode');
        add('ff=use ''scandisplayroutine:'' to convert the data to a string');
        add('*/');
        add('db 2 //2=4 byte notation');
        add('');
        add('scandisplayroutine:');
        add('/*');
        add('displayroutine is a ''special'' globally registered symbol (No need to alloc)');
        add('if ''scandisplayroutinetype:'' is set to 255 then this routine will be called to');
        add('convert the value at the address specified to a ascii-string');
        add('eax=pointer to bytes at the address');
        add('edx=pointer to destination string (max 50 chars)');
        add('');
        add('note: scandisplayroutine is only 16KB big');
        add('*/');
        add('mov [edx],"N" //NYI, not yet implemented');
        add('mov [edx+1],"Y"');
        add('mov [edx+2],"I"');
        add('mov [edx+3],0');
        add('ret');

        add('');
        add('');
        add('[disable]');
        add('dealloc(checkroutine)');
        add('dealloc(prologue,2048)');
        add('dealloc(epilogue,2048)');
        add('dealloc(fastscanstepsize)');
        add('dealloc(variablesize)');
        add('dealloc(scantext)');
        add('dealloc(scanvalue)');
        add('dealloc(singlescanvalue)');
        add('dealloc(doublescanvalue)');
      end;

      new1.Enabled:=false;

      editscript:=true;
      injectintomyself:=true;

      if showmodal=mrok then
      begin
        scriptname:='script '+inttostr(length(customscanscripts)+1);
        if not inputquery(strCustomScanConfig,'The script seems to be valid. What is the name of this script?',scriptname) then exit;

        //create a new entry in the custom list
        i:=length(customscanscripts);
        setlength(CustomScanScripts,i+1);

        CustomScanScripts[i].name:=scriptname;
        CustomScanScripts[i].data:=tstringlist.create;
        CustomScanScripts[i].data.Text:=assemblescreen.Text;
        CustomScanScripts[i].CustomScanType:=cstAutoAssembler;

        UpdateScanType; //reload the custom script list

        scantype.ItemIndex:=i;
      end;
    finally
      free; //clean up
    end;
  end;


end;

procedure TMainForm.ScanTypeKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var i: integer;
    index: integer;
begin
  index:=scantype.itemindex;

  if (key=vk_delete) and (getSelectedVariableType=vtCustom) and (index>=0) then //custom scan and something is selected
    if  messagedlg('Delete this custom script?',mtConfirmation,[mbyes,mbno],0)=mryes then
    begin
      CustomScanScripts[index].data.free;
      for i:=index to length(customscanscripts)-2 do
        CustomScanScripts[i]:=CustomScanScripts[i+1];

      setlength(CustomScanScripts,length(CustomScanScripts)-1);
      scantype.Items.Delete(index);

      if length(CustomScanScripts)>=index then
        scantype.ItemIndex:=length(CustomScanScripts)-1;

      scantype.Refresh;
    end;

end;

procedure TMainForm.HeaderControl1SectionClick(
  HeaderControl: THeaderControl; Section: THeaderSection);
begin
  if editingscript then exit; //no sorting till the edit is done

  case section.Index of
    0: sortbyfrozenbutton.Click;
    1: sortbydescriptionbutton.Click;
    2: sortbyaddressbutton.Click;
    3: sortbytypebutton.Click;
    4: sortbyvaluebutton.Click;
  end;
end;

procedure TMainForm.HeaderControl1SectionResize(
  HeaderControl: THeaderControl; Section: THeaderSection);
var x: integer;
begin
  x:=(headercontrol1.Sections[headercontrol1.Sections.Count-1].Left+headercontrol1.Sections[headercontrol1.Sections.Count-1].Width);
  scrollbox1.HorzScrollBar.Range:=x;
  resizescreen;

end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
  saveformposition(self,[
                        headercontrol1.Sections[0].Width,
                        headercontrol1.Sections[1].Width,
                        headercontrol1.Sections[2].Width,
                        headercontrol1.Sections[3].Width,
                        headercontrol1.Sections[4].Width,
                        panel5.height,
                        foundlist3.columns[0].width
                        ]);


end;

procedure TMainForm.tbSpeedChange(Sender: TObject);
var x: integer;
    y: single;
begin
  x:=tbSpeed.position;
  case x of
    0: y:=0;
    1: y:=0.5;
    2: y:=1;
    3: y:=2;
    4: y:=5;
    5: y:=10;
    6: y:=20;
    7: y:=50;
    8: y:=100;
    9: y:=200;
    10: y:=500;    
    else y:=1;
  end;
  editSH2.text:=format('%.1f',[y]);
end;

procedure TMainForm.btnSetSpeedhack2Click(Sender: TObject);
var newspeed: single;
    fs: Tformatsettings;
    error: boolean;
begin
  error:=false;
  try
    newspeed:=StrToFloat(editsh2.Text);
  except
    GetLocaleFormatSettings(GetThreadLocale, fs);
    try
      newspeed:=StrToFloat(editsh2.Text, fs);
    except
      error:=true;
    end;
  end;

  if error or IsInfinite(newspeed) or IsNan(newspeed) then
    raise exception.Create(editSH2.text+' is not a valid speed');

  if speedHack<>nil then
    speedhack.setSpeed(newspeed);
end;

procedure TMainForm.cbSpeedhackClick(Sender: TObject);
begin
  if formsettings.cbOldSpeedhack.checked then
  begin
    cbfastscanclick(sender);
    exit;
  end;

  if cbSpeedhack.Checked then
  begin
    try
      if speedhack<>nil then
        freeandnil(speedhack);
        
      speedhack:=TSpeedhack.create;
    except
      on e: exception do
      begin
        cbSpeedhack.checked:=false;
        raise exception.create(e.Message);
      end;
    end;
  end
  else
  begin
    if speedhack<>nil then
      freeandnil(speedhack);
  end;

  panel14.Visible:=cbSpeedhack.Checked;
end;

procedure TMainForm.Edit2Change(Sender: TObject);
begin
  editSH2.text:=edit2.text;
end;

{--------Processlist menuitem--------}
var il: TImageList;
procedure TMainForm.Process1Click(Sender: TObject);
var sl: tstringlist;
    mi: array of TMenuItem;
    currentmi: TMenuItemExtra;
    i,j: integer;

    tempicon: graphics.TIcon;

begin
  //fill with processlist
  if il=nil then
    il:=TImageList.Create(self);


  il.Clear;

  Menu.Images:=il;

  sl:=tstringlist.Create;

  try
    GetProcessList(sl);
    for i:=process1.Count-1 downto 3 do
      process1.Items[i].Free;

    setlength(mi,sl.count);
    for i:=0 to sl.count-1 do
    begin
      j:=sl.count-1-i;
      currentmi:=TMenuItemExtra.Create(self);
      currentmi.Caption:=sl[i];
      currentmi.Default:=dword(sl.Objects[i])=ProcessID;
      currentmi.data:=pointer(PProcessListInfo(sl.Objects[i])^.processid);
      currentmi.OnClick:=ProcessItemClick;

      if PProcessListInfo(sl.Objects[i])^.processIcon>0 then
      begin
        tempicon:=graphics.TIcon.Create;
        tempicon.handle:=PProcessListInfo(sl.Objects[i])^.processIcon;
        il.AddIcon(tempicon);
        tempicon.Free;

        currentmi.ImageIndex:=il.Count-1;
      end else
        currentmi.ImageIndex:=-1;

      mi[j]:=currentmi;
    end;

    process1.Add(mi);
  finally
    for i:=0 to sl.Count-1 do
      if sl.Objects[i]<>nil then
         freemem(pointer(sl.Objects[i]));
    sl.free;
  end;
end;

procedure TMainForm.ProcessItemClick(Sender: TObject);
var pid: dword;
    oldprocess: Dword;
    oldprocesshandle: thandle;
    oldprocessname: string;
begin
  if openprocessPrologue then
  begin
    oldprocessname:=copy(mainform.ProcessLabel.Caption,pos('-',mainform.ProcessLabel.Caption)+1,length(mainform.ProcessLabel.Caption));
    oldprocess:=processID;
    oldprocesshandle:=processhandle;
    if (sender is TMenuItemExtra) then
    begin
      pid:=dword(TMenuItemExtra(sender).data);

      unpause;
      DetachIfPossible;

      with TProcessWindow.Create(self) do
      begin
        pwop(inttohex(pid,8));
        ProcessLabel.caption:=StripHotkey(TMenuItemExtra(sender).Caption);
        free;
      end;

      openprocessepilogue(oldprocessname,oldprocess,oldprocesshandle);

    end;
  end;
end;


{^^^^^^^^Processlist menuitem^^^^^^^^}
procedure TMainForm.About1Click(Sender: TObject);
begin
  About:=TAbout.create(self);
  About.showmodal;
end;

procedure TMainForm.CreateProcess1Click(Sender: TObject);
var x: dword;
    oldprocess: Dword;
    oldprocesshandle: thandle;
    oldprocessname: string;
begin
  if openprocessPrologue then
  begin

    oldprocessname:=copy(mainform.ProcessLabel.Caption,pos('-',mainform.ProcessLabel.Caption)+1,length(mainform.ProcessLabel.Caption));
    oldprocess:=processID;
    oldprocesshandle:=processhandle;
    with TProcessWindow.Create(self) do
    begin
      button3.Click;
      free;
    end;

    if processid<>oldprocess then
      openprocessepilogue(oldprocessname,oldprocess,oldprocesshandle);

  end;
end;

procedure TMainForm.Helpindex1Click(Sender: TObject);
begin
  Application.HelpContext(1);
end;

procedure TMainForm.New1Click(Sender: TObject);
begin
  if MessageDlg('Are you sure you want to erase the data in the current table?',mtconfirmation, [mbyes,mbno],0)=mryes then
    clearlist;
end;

procedure TMainForm.ClearList;
{
Will remove all entries from the cheattable, comments, and advanced options window
}
begin
  Comments.Memo1.Clear;
  comments.Memo1.Lines.Add(strInfoAboutTable);
  Numberofrecords:=0;
  advancedoptions.codelist2.items.clear;
  advancedoptions.numberofcodes:=0;
  Updatescreen;
  Updatelist;
end;

procedure TMainForm.actScriptEngineExecute(Sender: TObject);
begin
  with TfrmCScript.create(self) do
    show;
end;

procedure TMainForm.File1Click(Sender: TObject);
begin
  menu.Images:=imagelist1;
end;

procedure TMainForm.Label61Click(Sender: TObject);
var c: string;
  startvalue,stopvalue: dword;
  s: tstringlist;
  i: integer;
  plist:PPointerlist;
begin
  if DBKDebug_WaitForDebugEvent(1000) then
  begin
    DBKDebug_ContinueDebugEvent(false);
  end
  else showmessage('timeout');
end;

procedure TMainForm.actOpenProcesslistExecute(Sender: TObject);
begin
  speedbutton1.Click;
end;

procedure TMainForm.Panel5Resize(Sender: TObject);
begin
  speedbutton3.top:=foundlist3.top+foundlist3.height-speedbutton3.Height;
  speedbutton3.left:=foundlist3.left+foundlist3.width+2;   
end;

procedure TMainForm.Foundlist3Resize(Sender: TObject);
begin
  beep;
end;

initialization

end.



